RBEC(权限管理系统)
2021/5/16 10:56:04
本文主要是介绍RBEC(权限管理系统),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
RBEC(权限管理系统)
1.RBEC的项目中重要性
在企业项目中,由于人员的权限不一样,而且也有临时更换或者改变权限的情况,增加了新的用户,或者增加了新的角色,增加新的权限也会需要改变,所以迫切需要一种动态的权限分配系统,也是提高项目安全性非常重要的保证。
2.所使用的技术
数据库:MySQL5.5
开发工具:IDEA2018
项目构建工具:Maven3.6.1
前端使用的技术:HTML5+jsp+layui+jQuery+zTree
后端使用的技术:MyBatis3.6.1,Spring5.2.7,SpringMVC 5.2.7
安全框架: Shiro
分页组件:PageHelper,Lomok,Druid,FastJson,ResultFul
服务器:Tomcat
一、数据库表结构的设计
#创建数据 CREATE DATABASE rbac; USER rbac; #部门表 CREATE TABLE sys_dept( id INT PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(32) ); #用户表 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) ); #角色表 CREATE TABLE sys_role( id INT PRIMARY KEY AUTO_INCREMENT, rolename VARCHAR(32) ); #用户角色中间表 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) ); #权限表 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 ); #角色权限中间表 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) );
#添加部门测试数据 INSERT INTO sys_dept(dname)VALUES('技术部'); INSERT INTO sys_dept(dname)VALUES('市场部'); INSERT INTO sys_dept(dname)VALUES('销售部'); #添加员工测试数据 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); #添加角色测试数据 INSERT INTO sys_role(rolename)VALUES('管理员'); INSERT INTO sys_role(rolename)VALUES('技术专员'); INSERT INTO sys_role(rolename)VALUES('市场专员'); #添加加权限测试数据 INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(0,'menu','权限管理系统','',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','用户管理',':',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','角色管理',':',1); INSERT INTO sys_permission(pid,TYPE,NAME,icon,OPEN)VALUES(1,'menu','权限管理',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:select','查询',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:add','增加',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:delete','删除',':',1); INSERT INTO sys_permission(pid,TYPE,percode,NAME,icon,OPEN)VALUES(2,'permission','user:delete','修改',':',1); #添加用户角色中间表 INSERT INTO sys_user_role(uid,rid)VALUES (1,1); INSERT INTO sys_user_role(uid,rid)VALUES(2,2); #添加角色权限中间表 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;
二、系统依赖
<dependencies> <!--测试所依赖的包--> <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所依赖的包--> <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所依赖的包--> <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所依赖的包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--由于mybatis底层还是用的jdbc:所以加入此依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!--数据库所依赖的包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <!--德鲁伊数据库连接池依赖包--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.2</version> </dependency> <!--mybatis和spring的整合包:由mybatis提供--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!--springmvc依赖的包--> <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所依赖的包--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!--日志所依赖的包--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <!--lombok所依赖的包--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--jstl的依赖--> <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>
三、用户登录功能
实体类
User 类:
@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 类:
@Data public class Dept { private Integer id; private String dname; //需要看这个部门有哪些员工就需要声明user private List<User> user; }
Permission 类:
@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 类:
@Data public class Role { private Integer id; private String rolename; private List<Permission> permissions; private List<User> users; }
接口
UserMapper 接口:
public interface UserMapper { /** * 通过telephoneAndPassword查询用户对象 * @param telephone * @param password * @return */ public User selectUserByTelephone(@Param("telephone") String telephone, @Param("password") String password); }
DeptMapper 接口:
public interface DeptMapper { public Dept selectDeptByDidWithStep(@Param("id") int id); }
RoleMapper 接口:
/** * 通过userid找到roleid * @author acoffee * @create 2021-05-11 19:46 */ public interface RoleMapper { public List<Role> selectRolesByUidWithStep(@Param("uid") int uid); }
Mapper映射文件
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>
配置文件
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> <!--作用:自动加载RequestMappingHandlerMapping和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> <!--配置上下文参数,ApplicationContext容器的实例化工作会交由WEB服务器完成,那么我们就要告诉WEB服务器spring配置文件的名称叫什么--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--配置监听器,监听spring配置文件--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置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> <!--表示容器在应用启动时就加载这个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"> <!--排除Controller:遇到@Controller注解不扫描--> <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> <!--配置事务管理器--> <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--注册事务管理器--> <tx:annotation-driven transaction-manager="transactionManger"></tx:annotation-driven> </beans>
Controller组件
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中的常用属性 value:实际上就是请求路径 method:表示限定的请求的方式:常用的 RequestMethod.POST、 RequestMethod.GET等 从spring4.3以后通过如下注解代替了请求方式: @GetMapping(value="/login")等价于 @RequestMapping(value = "/login",method = RequestMethod.GET) @POSTMapping(value="/login")等价于 @RequestMapping(value = "/login",method = RequestMethod.POST) */ @RequestMapping(value = "/login",method = RequestMethod.POST) /** * SpringMVC接收客户端的请求参数的方式 * 1.使用原始servlet的写法 * 缺点:(1)不能使用spring框架提供的内置类型转换器,还需要手动转换 * (2)与servlet的耦合性比较强 * 2.通过控制器处理方法的形参和表单对应的值对应的方式获取 * 好处:相对于第一种可以不用处理类型转换 * 缺点:如果表单的name和处理器的形参名称不对应就接收不到 * 如果两者不对应,在springmvc提供了一个注解@RequestParam可以设置 */ 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(); //保存到session中 session.setAttribute("USER_SESSION",result); //如果是转发 // modelAndView.setViewName("/index.jsp"); //如果是重定向 String contextPath = request.getContextPath(); modelAndView.setViewName("redirect:index.jsp"); return modelAndView; } }
jsp页面
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;"> 欢迎:${USER_SESSION.realname},角色:<c:forEach var="role" items="${USER_SESSION.roles}">${role.rolename}</c:forEach>,部门:${USER_SESSION.dept.dname} </div> </body> </html>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录页面</title> </head> <body> <form action="login" method="post"> <table> <tr> <td><label>手机号:</label></td> <td><input type="text" name="telephone"></td> </tr> <tr> <td><label>密码:</label></td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"> <input type="submit" value="登录"> </td> </tr> </table> </form> </body> </html>
service层
UserService 接口
public interface UserService { public User login(String telephone,String password); }
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); } }
登录页面
登录功能执行结果:
四、使用pageHelper完成分页功能
1.在pom.xml 文件中添加pageHelper依赖
<!-- 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.在spring-mybatis.xml文件中sqlSessionFactory的bean节点中
<property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql </value> </property> </bean> </array> </property>
实体对象
UserVo
/** * 页面的设置 * @author acoffee * @create 2021-05-14 15:09 */ @Data public class UserVo extends User { private Integer pageSize=1;//页数 private Integer count=5;//每页条目数 }
配置文件
UserMapper(在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> <!--通过电话号码和部门id查询--> <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>
前端页面
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;"> 欢迎:${USER_SESSION.realname},角色:<c:forEach var="role" items="${USER_SESSION.roles}">${role.rolename}</c:forEach>,部门:${USER_SESSION.dept.dname} <a href="<%=request.getContextPath()%>/user/list">查询用户列表</a> </div> </body> </html>
list.jsp(查询结果表单页面)
<%@ 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>用户列表信息</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; //与查到的具体部门和电话的表单绑定(点击上一页和下一页不会变回原来整体的页面) 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">--请选择部门--</option> <option value="1" ${uv.dept.id==1?"selected":""}>销售部</option> <option value="2" ${uv.dept.id==2?"selected":""}>技术部</option> <option value="3" ${uv.dept.id==3?"selected":""}>市场部</option> </select> <input type="submit" value="搜索"> </form> <tr> <td>编号</td> <td>手机号</td> <td>密码</td> <td>姓名</td> <td>生日</td> <td>头像</td> <td>状态</td> <td>部门</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?"正常":"禁用"}</td> <td>${user.dept.dname}</td> </tr> </c:forEach> </table> <div> <ul> <li><a href="javascript:goPage(${uv.pageSize-1})">上一页</a></li> <li><a href="javascript:goPage(${uv.pageSize+1})">下一页</a></li> </ul> </div> </body> </html>
Controller组件
UserController
/** * @author acoffee * @create 2021-05-14 15:38 */ @Controller @RequestMapping(value = "/user") public class UserController { @Autowired private UserService userService; /** * 控制器中的处理方法的返回值为跳转路径 * 此功能讲解从前台传递对象到控制器 * 如果使用的是对象的传值,那些只要前台的表单的name的值和对象中的属性名的值相同就可以接受到数据 */ @RequestMapping(value="/list") public String list(UserVo userVo, HttpServletRequest request){ List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist",userList);//转发设置到requset域中 request.setAttribute("uv",userVo); return "/user/list.jsp"; } }
执行效果
查询全部
查询具体部门
通过电话号码查询
同时通过电话号码和部门查询
五、增加用户功能
接口
UserMapper
public interface UserMapper { /** * 通过telephoneAndPassword查询用户对象 * @param telephone * @param password * @return */ public User selectUserByTelephone(@Param("telephone") String telephone, @Param("password") String password); /** * 分页查询 * @param condition * @return */ public List<User> selectUsersByUser(User condition); /** * 增加用户 * @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); }
配置文件
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> <!--通过电话号码和部门id查询--> <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> <!--配置上下文参数,ApplicationContext容器的实例化工作会交由WEB服务器完成,那么我们就要告诉WEB服务器spring配置文件的名称叫什么--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--配置监听器,监听spring配置文件--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--乱码的过滤器--> <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> <!--配置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> <!--表示容器在应用启动时就加载这个servlet--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
实现类
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); } }
控制器
BaseController
/** * 时间格式处理 * @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{ // //如果我们将@InitBinder配置在UserController中就只对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; /** * 控制器中的处理方法的返回值为跳转路径 * 此功能讲解从前台传递对象到控制器 * 如果使用的是对象的传值,那些只要前台的表单的name的值和对象中的属性名的值相同就可以接受到数据 */ @RequestMapping(value = "/list") public String list(UserVo userVo, HttpServletRequest request) { List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist", userList);//转发设置到requset域中 request.setAttribute("uv", userVo); return "/user/list.jsp"; } @RequestMapping("/goAddUser") public ModelAndView goAddUser() { ModelAndView modelAndView = new ModelAndView(); List<Dept> deptList = deptService.findAllDepts(); //通过ModelAndView存放的数据全部是放在request域对象中的 modelAndView.addObject("deptList", deptList); modelAndView.setViewName("/user/add.jsp"); return modelAndView; } @RequestMapping(value = "/addUser") public String addUser(User user){ /* 正常情况下,springmvc只把前台为yyyy/MM/dd的格式的时间字符串转成java.util.Date 在springmvc中要自定义类型转换有两种方法: 第一种方法:自定义转换器 */ logger.info("手机号:"+user.getTelephone()); logger.info("密码:"+user.getPassword()); logger.info("姓名:"+user.getRealname()); logger.info("生日:"+user.getBirthday()); logger.info("头像:"+user.getHeadimg()); logger.info("状态:"+user.getAvailable()); logger.info("部门:"+user.getDept()); logger.info("部门id:"+user.getDept().getId()); this.userService.addUser(user); return "list"; } }
前台页面
在list.jsp中添加此标签
<a href="${pageContext.request.contextPath}/user/goAddUser">增加用户</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="请输入手机号" class="input"></td> </tr> <tr> <td><input type="text" name="password" placeholder="请输入密码" class="input"></td> </tr> <tr> <td><input type="text" name="realname" placeholder="请输入姓名" class="input"></td> </tr> <tr> <td><input type="date" name="birthday" placeholder="请输入生日" class="input"></td> </tr> <tr> <td><input type="text" name="headimg" placeholder="请输入头像" class="input"></td> </tr> <tr> <td><input type="radio" name="available" value="1" checked>启用 <input type="radio" name="available" value="0">禁用</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="提交"> <input type="reset" value="重置"> </td> </tr> </table> </form> </body> </html>
执行结果:
add.jsp页面
添加过程
添加功能有两个主要的难点一个就是生日日期的格式问题,还有一个就是姓名乱码问题:
一、生日日期格式问题
出现生日日期格式问题会报400错误
遇到如上错误应该怎么处理,我们有两种处理方式:
如果我们在前台输入的时间格式为yyyy/MM/dd,那么这样也可以去得到正确的数据,因为springmvc框架默认会时间格式为yyyy/MM/dd这样的时间格式转成时间对象
那么我不习惯使用这种格式,我需要用我自己的格式,yyyy-MM-dd,就需要编写自定义类型转换器:
自定义类型转换器有两种方案
第1种方式∶自定义类实现Converter接口方式实现步骤
①编写自定义类,实现Converter接口,复写相关方法
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("时间类型转换错误"); } } }
②在springmvc的配置文件中声明转化换器
<?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> <!--此处要引用conversionServiceFactory--> <!--作用:自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter--> <mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven> </beans>
第2种方式∶使用@InitBinder实现时间转换实现步骤
1)自定义BaseController
public class BaseController { @InitBinder public void initBinder(WebDataBinder webDataBinder){ webDataBinder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } }
哪个控制器要用这个时间类型转换器,就需要继承BaseController
而我们是用的第二种方法来处理格式问题.
二、姓名乱码问题
当我们姓名输入中文时会出现乱码问题,解决方法如下:
在web.xml中添加乱码过滤器
<!--乱码的过滤器--> <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>
六、文件上传功能
我们这里做的主要是头像的上传功能
1.添加依赖:
<!--文件上传所依赖的包--> <!-- 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.在add.jsp中的from标签中配置enctype
上传有三个要求:
①我们必须用enctype的值是multipart/form-data进行封装,封装成多步请求后,他就可以进行文件上传
②必须是post请求
③上传的文件的type是file
<form action="<%=request.getContextPath()%>/user/addUser" method="post" enctype="multipart/form-data">
enctype就是encodetype就是编码类型的意思。
multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
将头像的格式改为file格式
<td><input type="file" name="headimg" placeholder="请输入头像" class="input"></td>
3.配置文件上传的解析器
<!--文件上传的解析器:bean的id值必须是multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--默认编码格式--> <property name="defaultEncoding" value="utf-8"></property> <!--字节计算:20*1024*1024=52428800 即20M--> <property name="maxUploadSize" value="52428800"></property> <!--缓存大小--> <property name="maxInMemorySize" value="40960"></property> </bean>
要注意,这里bean的id名称必须是multipartResolver,如果写成其他的就会报java.lang.IllegalStatrException的错误。
这个bean的id是有讲究的,当DispatcherServlet查找multipart解析器时,会查找id为multipartResolver的Bean。若定义的bean id 不是multipartResolver,DispatcherServlet会对它进行忽略。
代码
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> <!--第一种方法--> <!--<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>--> <!--第二种方法--> <mvc:default-servlet-handler></mvc:default-servlet-handler> <mvc:annotation-driven></mvc:annotation-driven> <!--文件上传的解析器:bean的id值必须是multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--默认编码格式--> <property name="defaultEncoding" value="utf-8"></property> <!--字节计算:20*1024*1024=52428800 即20M--> <property name="maxUploadSize" value="52428800"></property> <!--缓存大小--> <property name="maxInMemorySize" value="40960"></property> </bean> </beans>
前台页面
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="请输入手机号" class="input"></td> </tr> <tr> <td><input type="text" name="password" placeholder="请输入密码" class="input"></td> </tr> <tr> <td><input type="text" name="realname" placeholder="请输入姓名" class="input"></td> </tr> <tr> <td><input type="date" name="birthday" placeholder="请输入生日" class="input"></td> </tr> <tr> <td><input type="file" name="file" placeholder="请输入头像" class="input"></td> </tr> <tr> <td><input type="radio" name="available" value="1" checked>启用 <input type="radio" name="available" value="0">禁用</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="提交"> <input type="reset" value="重置"> </td> </tr> </table> </form> </body> </html>
控制器
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; /** * 控制器中的处理方法的返回值为跳转路径 * 此功能讲解从前台传递对象到控制器 * 如果使用的是对象的传值,那些只要前台的表单的name的值和对象中的属性名的值相同就可以接受到数据 */ @RequestMapping(value = "/list") public String list(UserVo userVo, HttpServletRequest request) { List<User> userList = userService.findUserByPage(userVo); request.setAttribute("userlist", userList);//转发设置到requset域中 request.setAttribute("uv", userVo); return "/user/list.jsp"; } @RequestMapping("/goAddUser") public ModelAndView goAddUser() { ModelAndView modelAndView = new ModelAndView(); List<Dept> deptList = deptService.findAllDepts(); //通过ModelAndView存放的数据全部是放在request域对象中的 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){ //获取服务器上路径,这里我们将图片传至服务器的指定文件夹,然后再从指定文件夹获取 String serverImageDirPath = request.getServletContext().getRealPath("/static/images"); logger.info("服务器上的图片文件夹的路径:"+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"; } }
执行结果
文件上传有一个难点,使用springmvc之后,你要引入所有的外部静态资源都没有办法引入原因是∶请求的时候会进入到核心控制器中,拦截了,解决的办法有两个:
1.在springmvc-config.xml文件中配置< mvc:resources>
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
2.在springmvc-config.xml文件中配置< mvc:default-servlet-handler>
<mvc:default-servlet-handler></mvc:default-servlet-handler>
做到这里我们基本上把这个简单的小项目就做完了。
这篇关于RBEC(权限管理系统)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28pyqt 怎么打包整个项目-icode9专业技术文章分享
- 2024-09-28laravel Commands 创建带有参数的 Artisan 命令的步骤和示例-icode9专业技术文章分享
- 2024-09-28antd怎么实现渲染tiff图片-icode9专业技术文章分享
- 2024-09-28英文半角中划线和中文全角的中划线有什么区别-icode9专业技术文章分享
- 2024-09-28nvm npm 和node 他们之间有什么关系-icode9专业技术文章分享
- 2024-09-28Node Version Manager (nvm)使用教程-icode9专业技术文章分享
- 2024-09-28nvm命令太慢,是什么原因-icode9专业技术文章分享
- 2024-09-28Kotlin 如何增加、删除和修改 MutableStateFlow 中的值。-icode9专业技术文章分享
- 2024-09-28Kotlin的stateFlow.update 写法介绍-icode9专业技术文章分享
- 2024-09-28kotlin 怎么获取当前时间格式-icode9专业技术文章分享