1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > OA系统实现(请假审批 mybatis)-1

OA系统实现(请假审批 mybatis)-1

时间:2020-11-22 12:03:56

相关推荐

OA系统实现(请假审批 mybatis)-1

办公自动化OA系统

1、办公自动化系统(Office Automation)是替代传统办公的解决方案

2、OA系统是利用软件技术构建的单位内部办公平台,用于辅助办公

3、利用OA系统可将办公数据数字化,可极大提高办公流程执行效率

第一步创建maven管理项目

第二部进行web工程设置

配置Tomcat

添加一个.html文件运行测试一下看看有没有问题

第三部 配置pop.xml 集成一系列组件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.imooc</groupId><artifactId>oa</artifactId><version>1.0-SNAPSHOT</version><repositories><repository><id>aliyun</id><name>aliyun</name><url>/repository/public</url></repository></repositories><dependencies><!--Mybatis框架--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><!--MySql8JDBC驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.17</version></dependency><!--Druid数据库连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.14</version></dependency><!--logback日志框架--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!--Junit测试框架--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies><!-- <build>--><!-- <plugins>--><!-- <plugin>--><!--&lt;!&ndash;利用Maven编译插件将编译级别提高到1.8解决&ndash;&gt;--><!--<groupId>org.apache.maven.plugins</groupId>--><!--&lt;!&ndash;maven-compiler-plugin是Maven自带的编译插件&ndash;&gt;--><!--<artifactId>maven-release-plugin</artifactId>--><!--<version>3.3</version>--><!--<configuration>--><!--&lt;!&ndash;检查源码按照1.8规则,默认1.5&ndash;&gt;--><!--<source>1.8</source>--><!--&lt;!&ndash;按4.8规则生成字节码&ndash;&gt;--><!--<target>1.8</target>--><!--</configuration>--><!-- </plugin>--><!-- </plugins>--><!-- </build>--><properties><piler.source>9</piler.source><piler.target>9</piler.target></properties></project>

创建并且编写mybatis-config.xml核心配置文件

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//com.//DTD Config 3.0//EN""/dtd/mybatis-3-config.dtd"><configuration><settings><!--驼峰命名转换 form_id -> formId--><setting name="mapUnderscoreToCamelCase" value="true"/></settings><environments default="dev"><!--开发环境配置--><environment id="dev"><!--事务管理器采用JDBC方式--><transactionManager type="JDBC"/><!--利用MyBatis自带连接池进行管理--><dataSource type="POOLED"><!--JDBC连接属性--><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/imooc-oa?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="youbenshashi"/></dataSource></environment></environments><mappers><mapper resource="mappers/test.xml"/></mappers></configuration>

创建MybatisUtils工具类

这里用到了Lambda表达式

lambda表达式

private static SqlSessionFactory sqlSessionFactory = null;static {Reader reader = null;try {// 加载配置文件。初始化sqlSessionFactoryreader = Resources.getResourceAsReader("mybatis-config.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);} catch (IOException e) {// 初始化错误throw new ExceptionInInitializerError(e);}}/*** 执行Select查询SQL* 这里使用了Function类,使用Lambda表达式更方便的实现SQL语句* @param func 要执行查询语句的代码块* @return 查询结果*/public static Object excuteQuery(Function<SqlSession, Object> func) {SqlSession sqlSession = sqlSessionFactory.openSession();try {return func.apply(sqlSession);} finally {sqlSession.close();}}/*** 执行Insert/update/delete写操作SQL* @param func 要执行写操作的代码块* @return 写操作后返回的结果*/public static Object excuteUpdate(Function<SqlSession, Object> func) {// 需要手动提交事务,将自动提交关闭SqlSession sqlSession = sqlSessionFactory.openSession(false);try {Object obj = func.apply(sqlSession);// 操作成功 提交事务mit();return obj;} catch (Exception e) {// 操作失败,回滚sqlSession.rollback();throw e;} finally {// 关闭sqlSessionsqlSession.close();}}

MyBatis整合Druid(alibaba)连接池

在java目录下创建一个用来初始化连接池的类

public class DruidDataSourceFactory extends UnpooledDataSourceFactory {public DruidDataSourceFactory() {// 将配置相关属性(xml)给dataSourcethis.dataSource = new DruidDataSource();}// 在这里初始化各种连接池(是否重写这个方法是需要根据使用的连接池属性来判断的)@Overridepublic DataSource getDataSource() {try {((DruidDataSource) this.dataSource).init();//初始化druid数据源} catch (SQLException e) {throw new RuntimeException(e);}return dataSource;}}

修改mybatis-config.xml配置文件

<!--MyBatis与Druid的整合--><!-- 上方自定义的类--><dataSource type="com.imooc.oa.datasource.DruidDataSourceFactory"><!--JDBC连接属性--><!-- driver修改为driverClassName 其他的不需要修改 --><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/imooc-oa?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="mima"/><!-- 初始连接数量 --><property name="initialSize" value="10"/><!-- 最大连接数量 --><property name="maxActive" value="20"/></dataSource>

运行查看是否配置正确

使用IDEA设置webapp目录的方法

整合Freemarker

在pop.xml增加Freemarker的依赖

<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.29</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><!--依赖只参与编译测试,不进行发布--><scope>provided</scope></dependency>

在web.xml文件中对Freemarker的配置

<servlet><!--FreemarkerServlet用于读取解析ftl文件--><servlet-name>freemarker</servlet-name><servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class><init-param><!--定义模板的存储路径--><param-name>TemplatePath</param-name><param-value>/WEB-INF/ftl</param-value></init-param><init-param><!--default_encoding用于设置读取ftl文件采用的字符集,避免中文乱码--><param-name>default_encoding</param-name><param-value>UTF-8</param-value></init-param></servlet><!--增加映射地址--><servlet-mapping><servlet-name>freemarker</servlet-name><url-pattern>*.ftl</url-pattern></servlet-mapping>

在配置的目录下创建ftl文件夹,把.html文件放入到该文件夹中并且修改.html为.ftl

将资源发布到lib包下,每次修改依赖后都要进行修改

增加logblack配置文件

在resources下添加配置文件

<?xml version="1.0" encoding="UTF-8" ?><configuration><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!--日志输出级别(优先级高到低):error:错误–系统的故障日志warn:警告-存在风险或使用不当的日志info:一般性消息debug:程序内部用于调试信息trace:程序运行的跟踪信息--><root level="debug"><appender-ref ref="console"/></root></configuration>

开发基于RBAC的权限控制模块

RBAC(Role-Based Access Control)-基于角色的访问控制

1.基于角色权限控制(RBAC)是面向企业安全策略的访问控制方式

2.RBAC核心思想是将控制访问的资源与角色(Role)进行绑定

3.系统的用户(User)与角色(Role)再进行绑定,用户便拥有对应权限

所有功能、资源都与角色(核心)进行绑定,系统用户对应角色,从而系统角色对应不同的资源,一个公司员工至少有一个系统用户账号。角色表是最重要的。

创建相关数据库

1.创建角色表(sys_role)

主键类型设置为Bigint 防止特殊情况。

2.创建资源(功能)表 (sys_node)

3.创建角色与资源(功能)的对应表(sys_role_node)

4.部门表(adm_department)

5.员工表(adm_employee)

6.用户表(sys_user)

7.用户与角色对应表(sys_role_user)

实现用户登录(前端)

基于LayUI开发登录页,需要在LayUI官网下载,然后将需要的文件粘贴到自己的项目中。

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>办公OA系统</title><link rel="stylesheet" href="/resources/layui/css/layui.css"><style>body {background-color: #F2F2F2;}.oa-container {/*background-color: white;*/position: absolute;width: 400px;height: 350px;top: 50%;left: 50%;padding: 20px;margin-left: -200px;margin-top: -175px;}#username, #password {text-align: center;font-size: 24px;}</style></head><body><div class="oa-container"><h1 style="text-align: center;margin-bottom: 20px">办公OA系统</h1><form class="layui-form"><div class="layui-form-item"><input type="text" id="username" lay-verify="required" name="username" placeholder="请输入用户名"autocapitalize="off"class="layui-input"></div><div class="layui-form-item"><!--lay-verify表单校验 required (必填项) --><input type="password" id="password" lay-verify="required" name="password" placeholder="请输入密码"autocapitalize="off"class="layui-input"></div><div class="layui-form-item"><button class="layui-btn layui-btn-fluid" lay-submit lay-filter="login">登录</button></div></form></div><script src="/resources/layui/layui.all.js"></script><script>layui.form.on("submit(login)", function (formdata) {// data包含了当前表单的数据console.log(formdata)layui.$.ajax({url: "/check_login",data: formdata.field,type: "post",dataType: "json",success: function (json) {console.log(json);if (json.code === "0") {// layui.layer.msg("登陆成功");window.location.href = json.redirect_url;} else {layui.layer.msg(json.message);}}})return false;//submit提交事件返回true则表单提交,false则阻止表单提交});</script></body></html>

实现用户登录(后端)

创建User实体类

public class User {private Long userId; // user_idprivate String username;private String password;private Long employeeId;private Integer salt;public Long getUserId() {return userId;}public void setUserId(Long userId) {this.userId = userId;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Long getEmployeeId() {return employeeId;}public void setEmployeeId(Long employeeId) {this.employeeId = employeeId;}public Integer getSalt() {return salt;}public void setSalt(Integer salt) {this.salt = salt;}}

新建一个mapper用来写SQL 语句

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="usermapper"><!--按用户名获取用户对象--><select id="selectByUsername" parameterType="String" resultType="com.imooc.oa.entity.User">select *from sys_userwhere username = #{value}</select></mapper>

在mybatis-config.xml中声明新建的mapper

<mappers><mapper resource="mappers/user.xml"/></mappers>

用mvc的开发方式。创建UserDao

public class UserDao {/*** 按用户名查找表* @param username 用户名* @return User对象包含对应的用户信息, null则代表对象不存在*/public User selectByUsername(String username) {return (User) MybatisUtils.executeQuery(SqlSession ->SqlSession.selectOne("usermapper.selectByUsername", username));}}

创建一个UserService

public class UserService {private UserDao userDao = new UserDao();private RbacDao rbacDao = new RbacDao();/*** 根据前台输入进行校验* @param username 前台输入的用户名* @param password 前台输入的密码* @return 校验通过后, 包含对应数据的User实体类* @throws BussinessException L001-用户名不存在,L002-密码错误*/public User checkLogin(String username, String password) {// 按用户名查找用户User user = userDao.selectByUsername(username);if (user == null) {// 抛出用户不存在异常throw new BussinessException("L001", "用户名不存在");}String md5 = MD5Utils.md5Digest(password, user.getSalt());if (!md5.equals(user.getPassword())) {throw new BussinessException("L002", "密码错误");}return user;}public List<Node> selectNodeByUserId(Long userId) {return rbacDao.selectNodeByUserId(userId);}}

自定义一个异常

public class BussinessException extends RuntimeException {private String code;// 异常编码,异常的标识private String message; // 异常具体文本消息 public BussinessException(String code, String message) {super(code + ":" + message);this.code = code;this.message = message;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}@Overridepublic String getMessage() {return message;}public void setMessage(String message) {this.message = message;}}

创建LoginServlet

@WebServlet(name = "LoginServlet", urlPatterns = "/check_login")public class LoginServlet extends HttpServlet {private UserService userService = new UserService();Logger logger = LoggerFactory.getLogger(LoginServlet.class);@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=utf-8");// 接收用户输入String username = request.getParameter("username");String password = request.getParameter("password");Map<String, Object> result = new HashMap<>();try {// 调用业务逻辑User user = userService.checkLogin(username, password);HttpSession session = request.getSession();session.setAttribute("login_user", user);result.put("code", "0");result.put("message", "success");result.put("redirect_url", "/index");} catch (BussinessException ex) {logger.error(ex.getMessage(), ex);result.put("code", ex.getCode());result.put("message", ex.getMessage());} catch (Exception ex) {logger.error(ex.getMessage(), ex);result.put("code", ex.getClass().getSimpleName());result.put("message", ex.getMessage());}// 返回对应结果String json = JSON.toJSONString(result);response.getWriter().println(json);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {}}

动态显示功能菜单

例如:获取编号为1的用户拥有哪些功能

通过用户找到角色,再通过角色找到节点编号,最后通过节点编号找到与之对应的其他信息

select DISTINCT n.*FROM sys_role_user ru,sys_role_node rn,sys_node nwhere ru.role_id = rn.role_idand user_id = 编号and rn.node_id = n.node_idORDER BY n.node_id

创建rbac.xml 同时记得注册登记

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="rbacmapper"><select id="selectNodeByUserId" resultType="com.imooc.oa.entity.Node" parameterType="Long">select DISTINCT n.*FROM sys_role_user ru,sys_role_node rn,sys_node nwhere ru.role_id = rn.role_idand user_id = #{value}and rn.node_id = n.node_idORDER BY n.node_id</select></mapper>

创建一个节点实体类。这里就不写了

创建一个RbacDao类。调用刚才的SQL

public class RbacDao {public List<Node> selectNodeByUserId(Long userId) {return (List<Node>) MybatisUtils.executeQuery(sqlSession -> sqlSession.selectList("rbacmapper.selectNodeByUserId", userId));}}

在UserService类中添加方法

public List<Node> selectNodeByUserId(Long userId) {return rbacDao.selectNodeByUserId(userId);}

如何在index界面中获取到用户的登录信息?

使用Session

根据用户登录的ID可以获取到该用户可用的模块列表(主要还是书写SQL语句)

@WebServlet(name = "IndexServlet", urlPatterns = "/index")public class IndexServlet extends HttpServlet {private UserService userService = new UserService();private EmployeeService employeeService = new EmployeeService();private DepartmentService departmentService = new DepartmentService();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {HttpSession session = request.getSession();// 得到当前登录用户对象User user = (User) session.getAttribute("login_user");// 获取当前登录的员工对象Employee employee = employeeService.selectById(user.getEmployeeId());// 获取员工对应的部门Department department = departmentService.selectById(employee.getDepartmentId());// 获取登录用户可用功能模板List<Node> nodeList = userService.selectNodeByUserId(user.getUserId());// 放入请求属性request.setAttribute("node_list", nodeList);session.setAttribute("current_employee", employee);session.setAttribute("current_department", department);// 请求派发至ftl进行展现request.getRequestDispatcher("/index.ftl").forward(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {}}

XML配置下实现Mapper接口

查询登录的员工

创建对应的实体类

创建一个新的接口

public interface EmployeeDao {/*** 根据ID号查询对应的员工* @param employeeId 员工ID* @return 员工信息*/public Employee selectById(Long employeeId);}

创建xml

<!--namespace与包名一致--><mapper namespace="com.imooc.oa.dao.EmployeeDao"><!--id与方法名对应parameterType与方法参数类型对应resultType与方法返回类型对应--><select id="selectById" parameterType="Long" resultType="com.imooc.oa.entity.Employee">select *from adm_employeewhere employee_id = #{value}</select></mapper>

在配置文件中配置mapper

<mappers><mapper resource="mappers/employee.xml"/></mappers>

新增Service

public class EmployeeService {public Employee selectById(Long employeeId) {return (Employee) MybatisUtils.executeQuery(sqlSession -> {EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);return employeeDao.selectById(employeeId);});}}

获取部门与这个流程一样

基于MD5算法对密码加密

MD5信息摘要算法广泛使用的密码散列函数

MD5可以产生出一个128位的散列值用于唯─标识源数据

项目中通常使用MD5作为敏感数据的加密算法

特点:

压缩性,MD5生成的摘要长度固定

抗修改,源数据哪怕有一个字节变化,MD5也会有巨大差异

不可逆,无法通过MD5反向推算源数据

Apache Commons CodeRc

Commons-Codec是Apache提供的编码/解码组件

通过Commons-Codec可轻易生成源数据的MD5摘要

MD5摘要方法: String md5 = DigestUtils.md5Hex(源数据)

在pop.xml中添加MD5摘要包

<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.14</version></dependency>

因为固定字符串MD5加密后都一样,所以我们要进行加盐处理。

public class MD5Utils {public static String md5Digest(String source) {return DigestUtils.md5Hex(source);}/*** 对源数据加盐混淆后生成MD5摘要* @param source 源数据* @param salt 盐值* @return MD5摘要*/public static String md5Digest(String source, Integer salt) {char[] ca = source.toCharArray();// 字符数组for (int i = 0; i < ca.length; i++) {ca[i] = (char) (ca[i] + salt);}String target = new String(ca);return DigestUtils.md5Hex(target);}public static void main(String[] args) {for (int i = 188; i <= 197; i++) {System.out.println(i);System.out.println(md5Digest("test", i));}}}

每个用户密码的盐值都不一样,在用户表中创建一个新字段用来存储对应的盐值。每次登录的时候获取用户输入的密码,然后将密码进行加盐MD5处理后判断是否与数据库中的密码相同。

注销操作

创建一个新的LogoutServlet

@WebServlet(name = "LogoutServlet", value = "/logout")public class LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {// 清空Sessionrequest.getSession().invalidate();// 重定向到登录页response.sendRedirect("/login.html");}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。