RBEC (rights management system)
1. Importance of RBEC in the project
In enterprise projects, due to the different permissions of personnel and the temporary change or change of permissions, the addition of new users or new roles will also need to be changed. Therefore, there is an urgent need for a dynamic permission allocation system, which is also a very important guarantee to improve project security.
2. Technology used
Mysql database: mysql.5 five
Development tool: IDEA2018
Project construction tool: Maven 3 six point one
Front end technology: HTML5+jsp+layui+jQuery+zTree
Back end technology: mybatis3 6.1,Spring5. 2.7,SpringMVC 5.2.7
Security framework: Shiro
Paging components: PageHelper, lomok, Druid, fastjason, resultful
Server: Tomcat
1, Design of database table structure
#Create data CREATE DATABASE rbac; USER rbac; #Department table CREATE TABLE sys_dept( id INT PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(32) ); #User table CREATE TABLE sys_user( id INT PRIMARY KEY AUTO_INCREMENT, telephone VARCHAR(11), PASSWORD VARCHAR(20), realname VARCHAR(32), birthday DATE, headimg VARCHAR(100), available INT(1), did INT, FOREIGN KEY(did)REFERENCES sys_dept(id) ); #Role table CREATE TABLE sys_role( id INT PRIMARY KEY AUTO_INCREMENT, rolename VARCHAR(32) ); #User role intermediate table CREATE TABLE sys_user_role( id INT PRIMARY KEY AUTO_INCREMENT, uid INT, rid INT, FOREIGN KEY (uid)REFERENCES sys_user(id), FOREIGN KEY(rid)REFERENCES sys_role(id) ); #Permission table CREATE TABLE sys_permission( id INT (11) PRIMARY KEY AUTO_INCREMENT, pid INT(11)DEFAULT NULL, TYPE VARCHAR(20)DEFAULT NULL, percode VARCHAR(20) DEFAULT NULL, NAIE VARCHAR(50)DEFAULT NULL, icon VARCHAR(100)DEFAULT NULL, href VARCHAR(200)DEFAULT NULL, OPEN INT DEFAULT 1 ); #Role permission intermediate table CREATE TABLE sys_role_permission( id INT PRIMARY KEY AUTO_INCREMENT, rid INT, perid INT, FOREIGN KEY(rid) REFERENCES sys_role(id), FOREIGN KEY(perid) REFERENCES sys_permission(id) );
#Add Department test data INSERT INTO sys_dept(dname)VALUES('Technology Department'); INSERT INTO sys_dept(dname)VALUES('Marketing Department'); INSERT INTO sys_dept(dname)VALUES('Sales Department'); #Add employee test data INSERT INTO sys_user(telephone,PASSWORD,realname,birthday,headimg,available,did)VALUES('13324537956','123456','giles','1980-09-09','static/upload/giles.jpg',1,1); INSERT INTO sys_user(telephone,PASSWORD,realname,birthday,headimg,available,did)VALUES('13324537952','123456','peter','1980-08-09','static/upload/peter.jpg',1,2); #Add role test data INSERT INTO sys_role(rolename)VALUES('administrators'); INSERT INTO sys_role(rolename)VALUES('technical attache'); INSERT INTO sys_role(rolename)VALUES('Marketing Specialist '); #Add permission test data INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(0,'menu','Authority management system','',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','user management ',':',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','Role management',':',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','Authority management',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:select','query',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:add','increase',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:delete','delete',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:delete','modify',':',1); #Add user role intermediate table INSERT INTO sys_user_role(uid,rid)VALUES (1,1); INSERT INTO sys_user_role(uid,rid)VALUES(2,2); #Add role permission intermediate table INSERT INTO sys_role_permission (rid,perid)VALUES(1,1); INSERT INTO sys_role_permission (rid,perid)VALUES(1,2); INSERT INTO sys_role_permission (rid,perid)VALUES(1,3); INSERT INTO sys_role_permission (rid,perid)VALUES(1,4); INSERT INTO sys_role_permission (rid,perid)VALUES(1,5); INSERT INTO sys_role_permission (rid,perid)VALUES(1,6); INSERT INTO sys_role_permission (rid,perid)VALUES(1,7); INSERT INTO sys_role_permission (rid,perid)VALUES(1,8); INSERT INTO sys_role_permission (rid,perid)VALUES(2,1); INSERT INTO sys_role_permission (rid,perid)VALUES(2,2); INSERT INTO sys_role_permission (rid,perid)VALUES(2,3); INSERT INTO sys_role_permission (rid,perid)VALUES(2,4); INSERT INTO sys_role_permission (rid,perid)VALUES(2,5); INSERT INTO sys_role_permission (rid,perid)VALUES(2,6); COMMIT;
2, System dependence
<dependencies> <!--Package on which the test depends--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.2.4.RELEASE</version> <scope>test</scope> </dependency> <!--spring Dependent package--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>5.2.7.RELEASE</version> <type>pom</type> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!--aop Dependent package--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!--mybatis Dependent package--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--because mybatis The bottom floor is still used jdbc: So join this dependency--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!--Package on which the database depends--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <!--Druid database connection pool dependency package--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.2</version> </dependency> <!--mybatis and spring Consolidation package for: mybatis provide--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!--springmvc Dependent packages--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!--servlet Dependent package--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!--Package on which the log depends--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <!--lombok Dependent package--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--jstl Dependence of--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> </dependencies>
3, User login function
Entity class
User class:
@Data public class User { private Integer id; private String telephone; private String password; private String realname; private Date birthday; private String headimg; private int available; private Dept dept; private List<Role> roles; }
Dept class:
@Data public class Dept { private Integer id; private String dname; //We need to see which employees in this department need to declare user private List<User> user; }
Permission class:
@Data public class Permission { private Integer id; private Integer pid; private String type; private String percode; private String name; private String icon; private String href; private int open; }
Role class:
@Data public class Role { private Integer id; private String rolename; private List<Permission> permissions; private List<User> users; }
Interface
UserMapper interface:
public interface UserMapper { /** * Query the user object through telephoneAndPassword * @param telephone * @param password * @return */ public User selectUserByTelephone(@Param("telephone") String telephone, @Param("password") String password); }
DeptMapper interface:
public interface DeptMapper { public Dept selectDeptByDidWithStep(@Param("id") int id); }
RoleMapper interface:
/** * roleid found by userid * @author acoffee * @create 2021-05-11 19:46 */ public interface RoleMapper { public List<Role> selectRolesByUidWithStep(@Param("uid") int uid); }
Mapper mapping file
DeptMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.acoffee.maven.mapper.DeptMapper"> <select id="selectDeptByDidWithStep" parameterType="int" resultType="Dept"> SELECT * FROM sys_dept where id=#{id} </select> </mapper>
RoleMapper:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.acoffee.maven.mapper.RoleMapper"> <select id="selectRolesByUidWithStep" parameterType="int" resultType="Role"> SELECT * FROM sys_role WHERE id IN(SELECT rid FROM sys_user_role WHERE uid=#{uid}) </select> </mapper>
UserMapper:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.acoffee.maven.mapper.UserMapper"> <resultMap id="userMap" type="User"> <id property="id" column="id"></id> <id property="telephone" column="telephone"></id> <id property="password" column="password"></id> <id property="realname" column="realname"></id> <id property="birthday" column="birthday"></id> <id property="headimg" column="headimg"></id> <id property="avaliable" column="avaliable"></id> <association property="dept" select="com.acoffee.maven.mapper.DeptMapper.selectDeptByDidWithStep" column="did"></association> <collection property="roles" select="com.acoffee.maven.mapper.RoleMapper.selectRolesByUidWithStep" column="id"></collection> </resultMap> <select id="selectUserByTelephone" resultMap="userMap"> select * from sys_user where telephone=#{telephone} and password=#{password} </select> </mapper>
configuration file
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="springmvc-config.xml"></import> <import resource="spring-mybatis.xml"></import> </beans>
springmvc-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.acoffee.maven.controller"></context:component-scan> <!--effect:Automatic loading RequestMappingHandlerMapping and RequestMappingHandlerAdapter--> <mvc:annotation-driven></mvc:annotation-driven> </beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_0.xsd"> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <!--Configure context parameters, ApplicationContext The instantiation of the container is left to the WEB The server is finished, then we have to tell WEB The server spring What is the name of the configuration file--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--Configure listener and monitor spring configuration file--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--to configure DisptacherServlet--> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <!--Indicates that the container loads this when the application starts servlet--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="com.acoffee.maven"> <!--exclude Controller:encounter@Controller Annotation not scanned--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter> </context:component-scan> <context:property-placeholder location="classpath:datasource.properties"></context:property-placeholder> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="initialSize" value="${initialSize}"></property> <property name="maxActive" value="${maxActive}"></property> <property name="maxWait" value="${maxWait}"></property> <property name="minIdle" value="${minIdle}"></property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="typeAliasesPackage" value="com.acoffee.maven.pojo"></property> <property name="configuration"> <bean class="org.apache.ibatis.session.Configuration"> <property name="aggressiveLazyLoading" value="false"></property> <property name="lazyLoadingEnabled" value="true"></property> </bean> </property> <property name="mapperLocations" value="classpath:/mapper/*.xml"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.acoffee.maven.mapper"></property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!--Configure transaction manager--> <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--Registration transaction manager--> <tx:annotation-driven transaction-manager="transactionManger"></tx:annotation-driven> </beans>
Controller component
LoginController
/** * @author acoffee * @create 2021-05-11 20:41 */ @Controller public class LoginController { private Logger logger = Logger.getLogger(this.getClass()); @Autowired private UserService userService; /* @RequestMapping Common properties in value:It's actually the request path method: The way to express a qualified request: commonly used requestmethod POST, RequestMethod.GET, etc From spring 4 3 later, the request method is replaced by the following notes: @GetMapping(value="/login")Equivalent to @ RequestMapping(value = "/login",method = RequestMethod.GET) @POSTMapping(value="/login")Equivalent to @ RequestMapping(value = "/login",method = RequestMethod.POST) */ @RequestMapping(value = "/login",method = RequestMethod.POST) /** * SpringMVC How to receive the request parameters of the client * 1.Write using the original servlet * Disadvantages: (1) the built-in type converter provided by spring framework cannot be used, and manual conversion is required * (2)It has strong coupling with servlet * 2.It is obtained by the way that the formal parameter of the controller processing method corresponds to the value corresponding to the form * Benefit: compared with the first method, you don't need to deal with type conversion * Disadvantages: if the name of the form does not correspond to the formal parameter name of the processor, it cannot be received * If the two do not correspond, spring MVC provides an annotation @ RequestParam, which can be set */ public ModelAndView login(@RequestParam("telephone") String telephone, @RequestParam("password") String password, HttpSession session, HttpServletRequest request){ User result = userService.login(telephone, password); ModelAndView modelAndView = new ModelAndView(); //Save to session session.setAttribute("USER_SESSION",result); //If forwarding // modelAndView.setViewName("/index.jsp"); //If redirected String contextPath = request.getContextPath(); modelAndView.setViewName("redirect:index.jsp"); return modelAndView; } }
jsp page
index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html; charset=UTF-8" language="java" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div style="right: 20px;"> welcome:${USER_SESSION.realname},role:<c:forEach var="role" items="${USER_SESSION.roles}">${role.rolename}</c:forEach>,department:${USER_SESSION.dept.dname} </div> </body> </html>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Login page</title> </head> <body> <form action="login" method="post"> <table> <tr> <td><label>cell-phone number:</label></td> <td><input type="text" name="telephone"></td> </tr> <tr> <td><label>password:</label></td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"> <input type="submit" value="Sign in"> </td> </tr> </table> </form> </body> </html>
service layer
UserService interface
public interface UserService { public User login(String telephone,String password); }
UserServiceImpl implementation class
@Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User login(String telephone, String password) { return userMapper.selectUserByTelephone(telephone,password); } }
Login page
Execution result of login function:
4, Use pageHelper to complete paging function
1. In POM Add pageHelper dependency to XML file
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.11</version> </dependency>
<property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql </value> </property> </bean> </array> </property>
2. In spring mybatis In the bean node of sqlSessionFactory in the XML file
<property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql </value> </property> </bean> </array> </property>
Entity object
UserVo
/** * Page settings * @author acoffee * @create 2021-05-14 15:09 */ @Data public class UserVo extends User { private Integer pageSize=1;//the number of pages private Integer count=5;//Entries per page }
configuration file
UserMapper (query criteria in UserMapper)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.acoffee.maven.mapper.UserMapper"> <resultMap id="userMap" type="User"> <id property="id" column="id"></id> <id property="telephone" column="telephone"></id> <id property="password" column="password"></id> <id property="realname" column="realname"></id> <id property="birthday" column="birthday"></id> <id property="headimg" column="headimg"></id> <id property="avaliable" column="avaliable"></id> <association property="dept" select="com.acoffee.maven.mapper.DeptMapper.selectDeptByDidWithStep" column="did"></association> <collection property="roles" select="com.acoffee.maven.mapper.RoleMapper.selectRolesByUidWithStep" column="id"></collection> </resultMap> <select id="selectUserByTelephone" resultMap="userMap"> select * from sys_user where telephone=#{telephone} and password=#{password} </select> <!--By telephone number and department id query--> <select id="selectUsersByUser" parameterType="user" resultMap="userMap"> SELECT * FROM sys_user <where> <if test="telephone != null and telephone!=''"> and telephone like concat('%',#{telephone},'%') </if> <if test="dept != null"> <if test="dept.id != null and dept.id != 0"> and did = #{dept.id} </if> </if> </where> </select> </mapper>
Front page
index. JSP (home page)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html; charset=UTF-8" language="java" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div style="right: 20px;"> welcome:${USER_SESSION.realname},role:<c:forEach var="role" items="${USER_SESSION.roles}">${role.rolename}</c:forEach>,department:${USER_SESSION.dept.dname} <a href="<%=request.getContextPath()%>/user/list">Query user list</a> </div> </body> </html>
list.jsp (query result form page)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <html> <head> <title>User list information</title> <style> ul{list-style: none} ul li{ float: left; } </style> <script> function goPage(pageSize) { var telephone = document.getElementById("telephone").value; var deptid = document.getElementById("deptid").value; //Bound to the form of the specific department and telephone found (clicking the previous page and the next page will not change back to the original overall page) window.location.href="${pageContext.request.contextPath}/user/list?pageSize="+pageSize+"&telephone="+telephone+"&dept.id="+deptid; } </script> </head> <body> <table> <form action="${pageContext.request.contextPath}/user/list" method="post"> <input id="telephone" type="text" name="telephone" value="${uv.telephone}"> <select id="deptid" name="dept.id"> <option value="0">--Please select a department--</option> <option value="1" ${uv.dept.id==1?"selected":""}>Sales Department</option> <option value="2" ${uv.dept.id==2?"selected":""}>Technology Department</option> <option value="3" ${uv.dept.id==3?"selected":""}>Marketing Department</option> </select> <input type="submit" value="search"> </form> <tr> <td>number</td> <td>cell-phone number</td> <td>password</td> <td>full name</td> <td>birthday</td> <td>head portrait</td> <td>state</td> <td>department</td> </tr> <c:forEach var="user" items="${userlist}"> <tr> <td>${user.id}</td> <td>${user.telephone}</td> <td>${user.password}</td> <td>${user.realname}</td> <td><fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate> </td> <td>${user.headimg}</td> <td>${user.available==1?"normal":"Disable"}</td> <td>${user.dept.dname}</td> </tr> </c:forEach> </table> <div> <ul> <li><a href="javascript:goPage(${uv.pageSize-1})">previous page</a></li> <li><a href="javascript:goPage(${uv.pageSize+1})">next page</a></li> </ul> </div> </body> </html>
Controller component
UserController
/** * @author acoffee * @create 2021-05-14 15:38 */ @Controller @RequestMapping(value = "/user") public class UserController { @Autowired private UserService userService; /** * The return value of the processing method in the controller is the jump path * This function explains the transfer of objects from the foreground to the controller * If the value transfer of the object is used, the data can be received as long as the value of the name of the foreground form is the same as the value of the attribute name in the object */ @RequestMapping(value="/list") public String list(UserVo userVo, HttpServletRequest request){ List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist",userList);//Forwarding settings to requset domain request.setAttribute("uv",userVo); return "/user/list.jsp"; } }
Execution effect
Query all
Query specific department
Query by phone number
At the same time, query through telephone number and department
5, Add user functions
Interface
UserMapper
public interface UserMapper { /** * Query the user object through telephoneAndPassword * @param telephone * @param password * @return */ public User selectUserByTelephone(@Param("telephone") String telephone, @Param("password") String password); /** * Paging query * @param condition * @return */ public List<User> selectUsersByUser(User condition); /** * Add users * @param user */ public void insertUser(User user); }
UserService
public interface UserService { public User login(String telephone,String password); public List<User> findUserByPage(UserVo userVo); public void addUser(User user); }
configuration file
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.acoffee.maven.mapper.UserMapper"> <resultMap id="userMap" type="User"> <id property="id" column="id"></id> <id property="telephone" column="telephone"></id> <id property="password" column="password"></id> <id property="realname" column="realname"></id> <id property="birthday" column="birthday"></id> <id property="headimg" column="headimg"></id> <id property="avaliable" column="avaliable"></id> <association property="dept" select="com.acoffee.maven.mapper.DeptMapper.selectDeptByDidWithStep" column="did"></association> <collection property="roles" select="com.acoffee.maven.mapper.RoleMapper.selectRolesByUidWithStep" column="id"></collection> </resultMap> <select id="selectUserByTelephone" resultMap="userMap"> select * from sys_user where telephone=#{telephone} and password=#{password} </select> <!--By telephone number and department id query--> <select id="selectUsersByUser" parameterType="user" resultMap="userMap"> SELECT * FROM sys_user <where> <if test="telephone != null and telephone!=''"> and telephone like concat('%',#{telephone},'%') </if> <if test="dept != null"> <if test="dept.id != null and dept.id != 0"> and did = #{dept.id} </if> </if> </where> </select> <insert id="insertUser" parameterType="user"> INSERT into sys_user(telephone,password,realname,birthday,available,did)values(#{telephone},#{password},#{realname},#{birthday},#{available},#{dept.id}) </insert> </mapper>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_0.xsd"> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <!--Configure context parameters, ApplicationContext The instantiation of the container is left to the WEB The server is finished, then we have to tell WEB The server spring What is the name of the configuration file--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--Configure listener and monitor spring configuration file--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--Garbled filter--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--to configure DisptacherServlet--> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-config.xml</param-value> </init-param> <!--Indicates that the container loads this when the application starts servlet--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Implementation class
UserServiceImpl
@Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User login(String telephone, String password) { return userMapper.selectUserByTelephone(telephone,password); } @Transactional(propagation = Propagation.NOT_SUPPORTED) @Override public List<User> findUserByPage(UserVo userVo) { PageHelper.startPage(userVo.getPageSize(),userVo.getCount()); return this.userMapper.selectUsersByUser(userVo); } @Override public void addUser(User user) { this.userMapper.insertUser(user); } }
controller
BaseController
/** * Time format processing * @author acoffee * @create 2021-05-15 9:13 */ public class BaseController { @InitBinder public void initBinder(WebDataBinder webDataBinder){ webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } }
UserController
/** * @author acoffee * @create 2021-05-14 15:38 */ @Controller @RequestMapping(value = "/user") public class UserController extends BaseController{ // //If we configure @ InitBinder in UserController, it is only valid for UserController // @InitBinder // public void initBinder(WebDataBinder webDataBinder){ // webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); // } private Logger logger = Logger.getLogger(this.getClass()); @Autowired private UserService userService; @Autowired private DeptService deptService; /** * The return value of the processing method in the controller is the jump path * This function explains the transfer of objects from the foreground to the controller * If the value transfer of the object is used, the data can be received as long as the value of the name of the foreground form is the same as the value of the attribute name in the object */ @RequestMapping(value = "/list") public String list(UserVo userVo, HttpServletRequest request) { List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist", userList);//Forwarding settings to requset domain request.setAttribute("uv", userVo); return "/user/list.jsp"; } @RequestMapping("/goAddUser") public ModelAndView goAddUser() { ModelAndView modelAndView = new ModelAndView(); List<Dept> deptList = deptService.findAllDepts(); //All the data stored through ModelAndView is placed in the request field object modelAndView.addObject("deptList", deptList); modelAndView.setViewName("/user/add.jsp"); return modelAndView; } @RequestMapping(value = "/addUser") public String addUser(User user){ /* Under normal circumstances, spring MVC only converts the time string in the format of yyyy/MM/dd to Java util. Date There are two ways to customize type conversion in spring MVC: The first method: customize the converter */ logger.info("cell-phone number:"+user.getTelephone()); logger.info("password:"+user.getPassword()); logger.info("full name:"+user.getRealname()); logger.info("birthday:"+user.getBirthday()); logger.info("head portrait:"+user.getHeadimg()); logger.info("Status:"+user.getAvailable()); logger.info("Department:"+user.getDept()); logger.info("department id: "+user.getDept().getId()); this.userService.addUser(user); return "list"; } }
Front page
On the list JSP
<a href="${pageContext.request.contextPath}/user/goAddUser">Add users</a>
add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .input{ width: 300px; height: 20px; border-radius: 5px; } </style> </head> <body> <form action="<%=request.getContextPath()%>/user/addUser" method="post"> <table> <tr> <td><input type="text" name="telephone" placeholder="Please enter your mobile number" class="input"></td> </tr> <tr> <td><input type="text" name="password" placeholder="Please input a password" class="input"></td> </tr> <tr> <td><input type="text" name="realname" placeholder="Please enter your name" class="input"></td> </tr> <tr> <td><input type="date" name="birthday" placeholder="Please enter birthday" class="input"></td> </tr> <tr> <td><input type="text" name="headimg" placeholder="Please enter Avatar" class="input"></td> </tr> <tr> <td><input type="radio" name="available" value="1" checked>Enable <input type="radio" name="available" value="0">Disable</td> </tr> <tr> <td> <select name="dept.id" class="input"> <c:forEach var="dept" items="${deptList}"> <option value="${dept.id}">${dept.dname}</option> </c:forEach> </select> </td> </tr> <tr> <td> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </td> </tr> </table> </form> </body> </html>
Execution result:
add.jsp page
Add process
There are two main difficulties in adding functions, one is the format of birthday date, and the other is the problem of name scrambling:
1, Birthday date format problem
400 error will be reported if there is a birthday date format problem
There are two ways to deal with the above errors:
If the time format we input in the foreground is yyyy/MM/dd, we can also get the correct data, because the spring MVC framework will convert the time format of yyyy/MM/dd into a time object by default
So I'm not used to using this format. I need to use my own format, yyyy MM DD, so I need to write a custom type converter:
There are two options for custom type converters
The first method: the implementation steps of the Converter interface implemented by the user-defined class
① Write custom classes, implement the Converter interface, and copy related methods
package com.acoffee.maven.convert; import org.springframework.core.convert.converter.Converter; import org.springframework.lang.Nullable; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * @author acoffee * @create 2021-05-14 20:33 */ public class StringToDateConverter implements Converter<String, Date> { private String pattern; public StringToDateConverter(String pattern) { this.pattern = pattern; } @Nullable @Override public Date convert(String s) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); try { return simpleDateFormat.parse(s); } catch (ParseException e) { throw new RuntimeException("Time type conversion error"); } } }
② Declare the converter in the configuration file of spring MVC
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.acoffee.maven.controller"></context:component-scan> <bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.acoffee.maven.convert.StringToDateConverter"> <constructor-arg index="0"> <value>yyyy-MM-dd</value> </constructor-arg> </bean> </list> </property> </bean> <!--Reference here conversionServiceFactory--> <!--effect:Automatic loading RequestMappingHandlerMapping and RequestMappingHandlerAdapter--> <mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven> </beans>
The second method: use @ InitBinder to realize the time conversion steps
1) Customize BaseController
public class BaseController { @InitBinder public void initBinder(WebDataBinder webDataBinder){ webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } }
The BaseController needs to inherit this type of time controller
We use the second method to deal with the format problem
2, Name garbled
When our name is entered in Chinese, there will be garbled code. The solution is as follows:
On the web Adding a garbled filter to XML
<!--Garbled filter--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
6, File upload function
What we do here is mainly the upload function of avatar
1. Add dependency:
<!--Package on which file upload depends--> <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
2. In add Configure enctype in the from tag in JSP
There are three requirements for uploading:
① We must encapsulate the value of enctype as multipart / form data. After encapsulating it into multi-step requests, he can upload files
② Must be a post request
③ The type of the uploaded file is file
<form action="<%=request.getContextPath()%>/user/addUser" method="post" enctype="multipart/form-data">
Encoding type means encoding type.
Multipart / form data means that form data is composed of multiple parts, including both text data and binary data such as files.
Change the format of the avatar to file format
<td><input type="file" name="headimg" placeholder="Please enter Avatar" class="input"></td>
3. Parser for uploading configuration files
<!--Parser for file upload: bean of id Value must be multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--Default encoding format--> <property name="defaultEncoding" value="utf-8"></property> <!--Byte calculation: 20*1024*1024=52428800 I.e. 20 M--> <property name="maxUploadSize" value="52428800"></property> <!--Cache size--> <property name="maxInMemorySize" value="40960"></property> </bean>
Note that the id name of the bean here must be multipartResolver. If it is written in other words, it will report Java Error in lang.illegalstatrexception.
The id of this bean is particular. When DispatcherServlet looks up the multipart parser, it will look up the bean with the id of multipart resolver. If defined bean id is not multipartResolver, dispatcher servlet will ignore it.
code
spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.acoffee.maven.controller"></context:component-scan> <!--The first method--> <!--<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>--> <!--The second method--> <mvc:default-servlet-handler></mvc:default-servlet-handler> <mvc:annotation-driven></mvc:annotation-driven> <!--Parser for file upload: bean of id Value must be multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--Default encoding format--> <property name="defaultEncoding" value="utf-8"></property> <!--Byte calculation: 20*1024*1024=52428800 I.e. 20 M--> <property name="maxUploadSize" value="52428800"></property> <!--Cache size--> <property name="maxInMemorySize" value="40960"></property> </bean> </beans>
Front page
add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .input{ width: 300px; height: 20px; border-radius: 5px; } </style> </head> <body> <form action="<%=request.getContextPath()%>/user/addUser" method="post" enctype="multipart/form-data"> <table> <tr> <td><input type="text" name="telephone" placeholder="Please enter your mobile number" class="input"></td> </tr> <tr> <td><input type="text" name="password" placeholder="Please input a password" class="input"></td> </tr> <tr> <td><input type="text" name="realname" placeholder="Please enter your name" class="input"></td> </tr> <tr> <td><input type="date" name="birthday" placeholder="Please enter birthday" class="input"></td> </tr> <tr> <td><input type="file" name="file" placeholder="Please enter Avatar" class="input"></td> </tr> <tr> <td><input type="radio" name="available" value="1" checked>Enable <input type="radio" name="available" value="0">Disable</td> </tr> <tr> <td> <select name="dept.id" class="input"> <c:forEach var="dept" items="${deptList}"> <option value="${dept.id}">${dept.dname}</option> </c:forEach> </select> </td> </tr> <tr> <td> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </td> </tr> </table> </form> </body> </html>
controller
UserController
@Controller @RequestMapping(value = "/user") public class UserController extends BaseController{ private Logger logger = Logger.getLogger(this.getClass()); @Autowired private UserService userService; @Autowired private DeptService deptService; /** * The return value of the processing method in the controller is the jump path * This function explains the transfer of objects from the foreground to the controller * If the value transfer of the object is used, the data can be received as long as the value of the name of the foreground form is the same as the value of the attribute name in the object */ @RequestMapping(value = "/list") public String list(UserVo userVo, HttpServletRequest request) { List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist", userList);//Forwarding settings to requset domain request.setAttribute("uv", userVo); return "/user/list.jsp"; } @RequestMapping("/goAddUser") public ModelAndView goAddUser() { ModelAndView modelAndView = new ModelAndView(); List<Dept> deptList = deptService.findAllDepts(); //All the data stored through ModelAndView is placed in the request field object modelAndView.addObject("deptList", deptList); modelAndView.setViewName("/user/add.jsp"); return modelAndView; } @RequestMapping(value = "/addUser") public String addUser(User user, @RequestParam("file") MultipartFile file, HttpServletRequest request){ //Get the path on the server. Here, we send the picture to the specified folder of the server, and then get it from the specified folder String serverImageDirPath = request.getServletContext().getRealPath("/static/images"); logger.info("Path to the picture folder on the server:"+serverImageDirPath); String imagePath = serverImageDirPath+"/"+file.getOriginalFilename(); File uploadImage = new File(imagePath); try { file.transferTo(uploadImage); user.setHeadimg(file.getOriginalFilename()); this.userService.addUser(user); } catch (IOException e) { e.printStackTrace(); } this.userService.addUser(user); return "list"; } }
results of enforcement
There is a difficulty in uploading files. After using spring MVC, you can't import all external static resources. The reason is that the request will enter the core controller and be intercepted. There are two solutions:
1. In springmvc config Configure < MVC: Resources > in XML file
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
2. In springmvc config Configure < MVC: default servlet handler > in the XML file
<mvc:default-servlet-handler></mvc:default-servlet-handler>
We have basically finished this simple small project.