Spring第七章:Spring+Mybatis快速开发

该系列为imooc Spring从入门到进阶笔记,跟随课程加入自己见解,同时也为项目中碰到一些问题做了解答

本门课程是使用使用Spring+Mybatis+Servlet开发人员信息管理系统

1、课程介绍

案例

  • 人员信息管理系统

前置条件

  • Mybatis、Spring、Servlet
  • Mysql

主要技术

  • Servlet、Jsp
  • Spring IOC、Spring AOP
  • Mybatis
  • Mybatis+Spring整合

课程开发环境

  • 操作系统 Win7
  • Web容器 Tomcat-8.5
  • 数据库 Mysql-5.7
  • 开发工具 IntelliJ IDEA
  • Spring 4.0.2.RELEASE
  • Mybatis 3.4.4

课程资料

项目结构

  • 三层架构

    • 持久层–Mybatis
    • 表现层–Servlet+Jsp
    • Spring–管理对象、切面处理
  • 基于MVC模式

    • 视图–Jsp
    • 模型–JavaBean
    • 控制器–Servlet+JavaBean

2、项目准备

2.1、数据库设计

在这里插入图片描述

2.2、SQL语句

drop database if exists sm;

create database sm;

use sm;


create table department(
	id int primary key auto_increment,
	name varchar(20) not null,
	address varchar(100)
);

create table staff(
	id int primary key auto_increment,
	account varchar(20) not null,
	password varchar(20) not null,
	status varchar(10) not null,
	did int,
	name varchar(20),
	sex char(2),
	id_number char(18),
	work_time datetime,
	leave_time datetime,
	born_date date,
	info varchar(200)
);

create table log(
	opr_time datetime not null,
	type varchar(10) not null,
	operator varchar(20) not null,
	moudle  varchar(20) not null,
	operation  varchar(20) not null,
	result  varchar(100) not null
);

alter table staff add constraint fk_staff_dep foreign key(did) references department(id);

2.3、项目搭建

sm– 父moudle

  • 全局定义与组织

sm_service– 子moudle

  • 持久层、业务层
  • Mybatis依赖、Spring依赖

sm_web– 子moudle

  • 表现层
  • Servlet依赖

1.创建sm– 父moudle
在这里插入图片描述

在这里插入图片描述
sm– 父moudle不实现具体功能,故src目录可以删掉

在这里插入图片描述

  1. 在父moudel下创建sm_service– 子moudle
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 在父moudel下创建sm_web– 子moudle

在这里插入图片描述

在这里插入图片描述

使用Override User settings file前提是在该指定路径下有settings.xml配置文件
在这里插入图片描述

2.4、配置POM文件

sm– 父moudle

    <properties>
        <spring.version>4.0.2.RELEASE</spring.version>
    </properties>

sm_service– 子moudle

    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

sm_web– 子moudle

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <parent>
        <artifactId>sm</artifactId>
        <groupId>com.imooc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>sm_web</artifactId>
    <packaging>war</packaging>
    <name>sm_web Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>sm_service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>sm_web</finalName>
    </build>
</project>

2.5、导入素材中的静态文件(css、js、图片)

在这里插入图片描述

2.6、Spring全局配置

  • Spring整合Mybatis
    • Spring用来做对象管理的,在项目中所有与功能相关的对象,都应有Spring进行管理
    • Mybatis用来做持久化操作,则必需管理若干个对象,比如:SqlSessionFactory、持久化操作对象(增删改查的功能对象)
    • Spring整合Mybatis,就是把Mybatis原来管理的对象交给Spring进行管理
  • 声明式事物
  • 全局扫描
<?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:aop="http://www.springframework.org/schema/aop"
       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/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--Spring整合Mybatis-->
    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/sm?useUnicode=true&amp;characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--Spring配置session工厂-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--简化实体类类名,配置后不用再使用全称(包名+类名),只需类名-->
        <property name="typeAliasesPackage" value="com.imooc.sm.entity"/>
    </bean>

    <!--Spring配置持久化对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.imooc.sm.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
    <!--以上配置完成了Spring对Mybatis配置,配置完成之后,将不再需要Mybatis的配置文件了,同时也把Mybatis原来管理的对象,交给了Spring进行管理-->

    <!--声明式事物配置-->
    <!--配置事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--指定事物的属性,get/find/search等方法不使用事物进行封装-->
            <tx:method name="get*"  read-only="true"/>
            <tx:method name="find*"  read-only="true"/>
            <tx:method name="search*"  read-only="true"/>

            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--植入的相关配置-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.imooc.sm.service.*.*(..))"/>
        <!--定义通知器(通知器跟切面一样,也包括通知和切点)-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
    <!--完成声明式事物配置-->
    
    <!--全局扫描-->
    <!--开启注解扫描-->
    <context:component-scan base-package="com.imooc.sm"/>
    <!--开启AspectJ自动代理-->
    <aop:aspectj-autoproxy/>
</beans>

2.7、工具类准备

工具类:指一个项目中,多个模块共同需要的功能,我们将其抽离出来专门放置在一个地方,其他模块需要的时候就去调用

目前项目各模块文件夹创建如图所示
在这里插入图片描述

2.7.1、编码过滤器

作为Web项目,所有模块都会去处理请求与响应,那么编码过滤器就是必须的,那么我们先实现工具类-编码过滤器

  1. sm_web模块>src>main>java>com.imooc.sm.global包下>新建EncodingFilter(编码过滤器)
package com.imooc.sm.global;

import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {

    private String encoding ="UTF-8";

    public void init(FilterConfig filterConfig) throws ServletException {
        if(filterConfig.getInitParameter("ENCODING")!=null)
            encoding = filterConfig.getInitParameter("ENCODING");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding(encoding);
        servletResponse.setCharacterEncoding(encoding);
        filterChain.doFilter(servletRequest,servletResponse);
    }

    public void destroy() {
        encoding=null;
    }
}
  1. 在sm_web模块中的web.xml配置过滤器
    通过Maven模板生成的web项目中,web.xml的模板可能不符合要求,可参照“课程介绍”提供的静态文件中的模板
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/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_1.xsd"
         version="3.1">
  <filter>
    <filter-name>Encoding</filter-name>
    <filter-class>com.imooc.sm.global.EncodingFilter</filter-class>
    <init-param>
      <param-name>ENCODING</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>Encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

2.7.2、核心控制器

为什么要有核心控制器

  • 当用户向web容器发送请求时,web容器会根据请求的url,判断是否该用Servlet以及用哪个Servlet处理。判断完成后它会构造出Servlet对象然后进行初始化,之后再调用service方法对请求进行处理。

  • 但是,Servlet对象由Web容器进行管理。service对象、dao对象(持久化操作对象)由IOC容器进行管理。Servlet对象处理用户请求时需要调用Service对象,根据IoC思想,你需要A对象我就自动帮你注入A对象,但是在这里是无法实现的。因为servlet对象不在IoC容器里(servlet对象不由IoC容器管理),所以没办法帮他注入需要的A对象,所以在Servlet对象无法使用spring_ioc进行Service对象的注入。

注意区分:
核心控制器
控制器指(图示中控制器1、2)

如何解决

  • 解决:核心控制器。
  • 用户发送请求到web容器,web容器将请求全部交给核心控制器(一个Servlet),核心控制器不做具体操作,只是判断该调用哪个控制器进行处理这次请求。
  • 那么这些控制器也是一个对象,且是被我们自己写的核心控制器进行选择调用,所以可以将这些控制器对象放到IOC容器里。再从IOC容器里获取这些控制器对象。
  • 也就是说,我接受用户的url,通过核心控制器解析之后判断是由哪个控制器来处理它,那么我就从IOC容器里把这个控制器的对象拿出来。因为控制器在ioc容器里,如果控制器需要调用service的一些功能,那么IOC容器自然可以帮他注入进来。

核心控制器干什么

  1. 解析url得到IOC容器里控制器的bean的名字
  2. 处理这一次请求匹配IOC容器里对应的控制器对应的方法。
    (通过控制器的bean的名字在IOC容器中把这个控制器bean对象拿出来,然后再通过该控制器的方法名反射执行该方法。)

并不是说说有请求都交给核心控制器,是有一定规范的请求才交给核心控制器,比如说以后缀名进行规范

在这里插入图片描述

  1. sm_web模块>src>main>java>com.imooc.sm.global包下>新建DispatcherServlet(核心控制器)
package com.imooc.sm.global;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DispatcherServlet extends GenericServlet {

    private ApplicationContext context;

    public void init() throws ServletException {
        super.init();
        //读取Spring配置文件,构造IOC容器
        context = new ClassPathXmlApplicationContext("spring.xml");
    }

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        /*请求规范
          访问路径规范:
                /staff/add.do——普通模块
                /login.do——特殊模块
          控制器命名规范:
                staffController
          控制器中方法命名规范:方法名称需要与"staff/add.do"中的"add"对应
                public void add(HttpServletRequest request, HttpServletResponse response){}
        *
         */

        /*获取用户请求的URL,去掉URL中第一个"/"*/
        /*访问路径就会变为这种格式:
                staff/add.do——普通模块
                login.do——特殊模块
        * */
        String path = request.getServletPath().substring(1);
        String beanName = null;
        String methodName = null;

        //再次查找"/"的位置
        int index = path.indexOf('/');
        if (index != -1) {//若还存在"/",则为staff/add.do——普通模块
            beanName = path.substring(0, index) + "Controller";//获取控制器名称,再次对访问路径进行截取,只保留"/"前的位置,如:staff
            methodName = path.substring(index + 1, path.indexOf(".do"));//获取控制器中方法名称,再次对访问路径进行截取,只保留"/"后直到"."的位置,如:add
        } else {//若不存在"/",则为login.do——特殊模块
            beanName = "selfController";
            methodName = path.substring(0, path.indexOf(".do"));
        }

        //从IOC容器中获取bean
        Object obj = context.getBean(beanName);

        //获取控制器方法
        try {
            Method method = obj.getClass().getMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
            method.invoke(obj,request,response);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

  1. 在sm_web模块中的web.xml配置
  <servlet>
    <servlet-name>Global</servlet-name>
    <servlet-class>com.imooc.sm.global.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Global</servlet-name>
    <url-pattern>*.do</url-pattern><!--所有以".do"为后缀的请求,全部交给核心控制器完成-->
  </servlet-mapping>

2.7.3、核心控制器测试

2.7.3.1、测试工具类、配置文件在语法上是否存在问题

1.在sm_web模块中的webapp下新建show.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/6/10
  Time: 8:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
你好,世界!
</body>
</html>

直接右键run show.jsp,此时idea会自动添加一个Tomcat的部署配置
在这里插入图片描述
若没有异常,页面会正常显示,访问路径为http://localhost:8080/show.jsp
若存在异常,检测Tomcat中的上下文路径Application context配置应为空

  • 在一个项目中 ,有很多页面要显示,但显示的内容通常是活的,并不是写死在页面上,内容可能是一些数据,那么此时就牵扯到数据传递的问题。
  • 而在MVC模式的要求下,JSP页面作为视图,是不允许主动获取数据抓取数据的,应该由控制器获取数据后,传递给JSP,所以接下来创建控制器来进行测试
2.7.3.2、测试显示信息控制器
  1. 在sm_web模块下>com.imooc.sm.controller包下>新建TestController类(test控制器)
package com.imooc.sm.controller;

import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Controller("testController")//通过注解将该控制器加入IOC容器,同时指定该控制器在IOC容器中的标识,该控制器的名称为test
public class TestController {

    /*该类中会存在若干个方法,每一个方法就是一个控制器方法,这些控制器方法访问路径需遵循这样一个规范
    *   比如访问路径为:/test/*.do
    *   其中"test"代表"@Controller("testController")"注解中的test+Controller中的test,即该控制器类的名称test
    *   其中"*"就代表方法名
    * */

    //show方法作为一个控制器方法,它的访问路径为:/test/show.do
    public void show(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //该控制器方法的功能为向页面传递数据
        request.setAttribute("NAME","张三");
        //传递结束后跳转show.jsp,"show.jsp"位置在sm_web模块下webapp文件夹下(根目录)即:/show.jsp
        //当前控制器方法的访问路径为:/test/show.do
        //说明show.jsp的位置在这个控制器show方法的上一层目录,故该控制器show方法访问show.jsp路径应为上一层的show.jsp
        request.getRequestDispatcher("../show.jsp").forward(request,response);
    }
}

启动Tomcat,在浏览器输入http://localhost:8080/test/show.do
在这里插入图片描述
核心控制器成功处理这一次请求匹配IOC容器里对应的控制器对应的方法

注意:访问路径为什么是/test/show.do
因为核心控制器本身就是我们自己编写的,在web.xml中我们配置了*.do的请求交个核心控制器
在这里插入图片描述
同时又在核心控制器里面分析路径时,我们判断的是访问路径以.do结尾
在这里插入图片描述

2.7.3.3、删除测试代码
  1. 删除show.jsp
  2. 删除com.imooc.sm.controller包下>TestController类
  3. 删除Tomcat部署
    在这里插入图片描述

3、功能实现

3.1、部门管理

实现对部门信息的增删改查

步骤

  • 实体类
  • Dao接口与Sql映射文件
  • Service接口与其实现类
  • 控制器
  • 页面

3.1.1、实现持久层

在sm_service模块下

  1. 在com.imooc.sm.entity包下>新建Department (实体类)
package com.imooc.sm.entity;

public class Department {
    private Integer id;
    private String name;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

  1. 在java文件夹下>com.imooc.sm.dao包下>新建DepartmentDao (持久化操作接口)
package com.imooc.sm.dao;

import com.imooc.sm.entity.Department;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository("departmentDao")
public interface DepartmentDao {
    void insert(Department department);
    void delete(Integer id);
    void update(Department department);
    Department selectById(Integer id);
    List<Department> selectAll();
}

  1. 创建映射文件DepartmentDao.xml
    在resources下创建com/imooc/sm/dao文件夹>创建映射文件DepartmentDao.xml

保持访问路径一致

  • DepartmentDao.xml映射文件放置在resources下的com/imooc/sm/dao文件夹中
  • 持久化操作接口DepartmentDao放置在java文件夹下的com.imooc.sm.dao包中
  • 这样才能保证所访问路径保持一致(访问路径一致,不是放置在同一个地方)

注意

在resources下创建目录
不能用com.imooc.sm.dao,因为这样创建出来的是一个一级目录,
只能使用com/imooc/sm/dao,这样创建出来的才是一个多级目录。
如果按照com.imooc.sm.dao创建目录,这样经过maven编译之后,xml文件和Dao接口不是在一个目录下!这样就无法进行映射了!    

保持映射文件名称 需与 持久化操作接口名称 一致

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--
mapper 用于定义一个映射配置文件的根节点
namespace属性是用来配置命名空间,主要进行session级别的缓存管理,命名空间默认情况下,使用我们当前操作的实体类的全路径
-->
<mapper namespace="com.imooc.sm.dao.DepartmentDao">

    <!--配置实体类与数据库表名映射关系-->
    <resultMap id="resultMap" type="Department">
        <!--property配置的是实体类的属性名称,column表示配置的是数据库字段名称-->
        <!--若实体类的属性对应的数据库字段是主键,则使用id标签-->
        <id property="id" column="id" javaType="Integer"/>
        <!--若实体类的属性对应的数据库字段不是主键,则使用result标签-->
        <result property="name" column="name" javaType="String"/>
        <result property="address" column="address" javaType="String"/>
    </resultMap>

    <!--配置SQL-->

    <!--parameterType为配置参数,useGeneratedKeys为调用数据库自增规范(可见MyBatis第十章)-->
    <insert id="insert" parameterType="Department" useGeneratedKeys="true">
        insert into department(name,address) values(#{name},#{address})
    </insert>

    <delete id="delete" parameterType="Integer">
        delete from department where id=#{id}
    </delete>

    <update id="update" parameterType="Department">
        update department set name=#{name},address=#{address} where id=#{id}
    </update>

    <!--resultMap表示返回的结果类型-->
    <select id="selectById" parameterType="Integer" resultMap="resultMap">
        select * from department where id=#{id}
    </select>

    <select id="selectAll" resultMap="resultMap">
        select * from department
    </select>
</mapper>

3.1.2、实现业务层

在sm_service模块下

  1. 在com.imooc.sm.service包下>新建DepartmentService (业务层接口)
package com.imooc.sm.service;

import com.imooc.sm.entity.Department;

import java.util.List;

public interface DepartmentService {
    void add(Department department);
    void remove(Integer id);
    void edit(Department department);
    Department get(Integer id);
    List<Department> getAll();
}

  1. 新建com.imooc.sm.service.impl包>新建DepartmentServiceImpl (业务层实现类)
package com.imooc.sm.service.impl;

import com.imooc.sm.dao.DepartmentDao;
import com.imooc.sm.entity.Department;
import com.imooc.sm.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service("departmentService")
public class DepartmentServiceImpl implements DepartmentService {
    @Autowired
    private DepartmentDao departmentDao;

    public void add(Department department) {
        departmentDao.insert(department);
    }

    public void remove(Integer id) {
        departmentDao.delete(id);
    }

    public void edit(Department department) {
        departmentDao.update(department);
    }

    public Department get(Integer id) {
        return departmentDao.selectById(id);
    }

    public List<Department> getAll() {
        return departmentDao.selectAll();
    }
}

3.1.3、实现表现层

在sm_web模块下

  1. com.imooc.sm.controller包下>新建DepartmentController (控制器)
package com.imooc.sm.controller;

import com.imooc.sm.entity.Department;
import com.imooc.sm.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Controller("departmentController")//通过注解将该控制器加入IOC容器,同时指定该控制器在IOC容器中的标识,该控制器的名称为department
public class DepartmentController {
    @Autowired
    private DepartmentService departmentService;

    //列表显示功能
    //list方法作为一个控制器方法,它的访问路径为:/department/list.do
    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Department> list = departmentService.getAll();
        request.setAttribute("LIST",list);
        //department_list.jsp页面作为视图
        //"department_list.jsp"位置在sm_web模块下webapp文件夹下(根目录)即:/department_list.jsp
        //说明department_list.jsp的位置在这个控制器list方法的上一层目录,故该控制器list方法访问department_list.jsp路径应为上一层的department_list.jsp
        request.getRequestDispatcher("../department_list.jsp").forward(request,response);
    }

    //跳转添加页面功能
    public void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("../department_add.jsp").forward(request,response);
    }

    //部门添加功能
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String address = request.getParameter("address");

        Department department = new Department();
        department.setName(name);
        department.setAddress(address);

        departmentService.add(department);
        response.sendRedirect("list.do");//响应重定向回控制器列表显示方法
    }

    //跳转修改数据页面功能
    public void toEdit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        Department department = departmentService.get(id);
        request.setAttribute("OBJ",department);//用于页面取该department对象原来设定的属性值
        request.getRequestDispatcher("../department_edit.jsp").forward(request,response);
    }

    //修改数据功能
    public void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        String name = request.getParameter("name");
        String address = request.getParameter("address");

        Department department = new Department();
        department.setId(id);
        department.setName(name);
        department.setAddress(address);

        departmentService.edit(department);
        response.sendRedirect("list.do");
    }

    //删除功能
    public void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        departmentService.remove(id);
        response.sendRedirect("list.do");
    }
}

JSP页面的编码,我就不放出来了,现在基本不会在使用JSP,该项目只是为了演示Spring+Mybatis+Servlet案例,大家可以自行通过案例源码下载查看

3.2、员工管理

实现员工信息的增删改查

关注点

  • 员工与部门的关联关系
  • 默认登陆密码

步骤

  • 实体类
  • Dao接口与Sql映射文件
  • Service接口与其实现类
  • 控制器
  • 页面

3.2.1、实现持久层

在sm_service模块下

  1. 在com.imooc.sm.entity包下>新建Staff (实体类)
package com.imooc.sm.entity;

import java.util.Date;

public class Staff {
    private Integer id;
    private String account;
    private String password;
    private String status;
    private Integer did;
    private String name;
    private String sex;
    private String idNumber;
    private Date workTime;
    private Date leaveTime;
    private Date bornDate;
    private String info;
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getIdNumber() {
        return idNumber;
    }

    public void setIdNumber(String idNumber) {
        this.idNumber = idNumber;
    }

    public Date getWorkTime() {
        return workTime;
    }

    public void setWorkTime(Date workTime) {
        this.workTime = workTime;
    }

    public Date getLeaveTime() {
        return leaveTime;
    }

    public void setLeaveTime(Date leaveTime) {
        this.leaveTime = leaveTime;
    }

    public Date getBornDate() {
        return bornDate;
    }

    public void setBornDate(Date bornDate) {
        this.bornDate = bornDate;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

需要注意
在数据库中字段类型为 datetime、date,在java中对应的类型为 java.util.Date

  1. 在java文件夹下>com.imooc.sm.dao包下>新建StaffDao (持久化操作接口)
package com.imooc.sm.dao;

import com.imooc.sm.entity.Staff;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository("staffDao")
public interface StaffDao {
    void insert(Staff staff);
    void delete(Integer id);
    void update(Staff staff);
    Staff selectById(Integer id);
    List<Staff> selectAll();
}

  1. 创建映射文件StaffDao.xml
    在resources下com/imooc/sm/dao文件夹>创建映射文件StaffDao.xml
    下面的映射文件中出现了多表联查,关于多表联查可以看看这篇文章
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.sm.dao.StaffDao">
    <resultMap id="resultMap" type="Staff">
        <id property="id" column="id" javaType="Integer"/>
        <result property="account" column="account" javaType="String"/>
        <result property="password" column="password" javaType="String"/>
        <result property="status" column="status" javaType="String"/>
        <result property="did" column="did" javaType="Integer"/>
        <result property="name" column="name" javaType="String"/>
        <result property="sex" column="sex" javaType="String"/>
        <result property="idNumber" column="id_number" javaType="String"/>
        <result property="workTime" column="work_time" javaType="java.util.Date"/>
        <result property="leaveTime" column="leave_time" javaType="java.util.Date"/>
        <result property="bornDate" column="born_date" javaType="java.util.Date"/>
        <result property="info" column="info" javaType="String"/>
        <!--配置多表联查-->
        <association property="department" column="did" javaType="Department" select="com.imooc.sm.dao.DepartmentDao.selectById" />
    </resultMap>

    <insert id="insert" parameterType="Staff" useGeneratedKeys="true">
        insert into staff(account,password,status,did,name,sex,id_number,work_time,leave_time,born_date,info)
        values(#{account},#{password},#{status},#{did},#{name},#{sex},#{idNumber},#{workTime},#{leaveTime},#{bornDate},#{info})
    </insert>
    <delete id="delete" parameterType="Integer">
        delete from staff where id=#{id}
    </delete>
    <update id="update" parameterType="Staff">
        update staff set account=#{account},password=#{password},status=#{status},
        did=#{did},name=#{name},sex=#{sex},id_number=#{idNumber},
        work_time=#{workTime},leave_time=#{leaveTime},born_date=#{bornDate},info=#{info} where id=#{id}
    </update>
    <select id="selectById" parameterType="Integer" resultMap="resultMap">
        select * from staff where id=#{id}
    </select>
    <select id="selectAll" resultMap="resultMap">
        select * from staff
    </select>
</mapper>

3.2.2、实现业务层

在sm_service模块下

  1. 在com.imooc.sm.service包下>新建StaffService (业务层接口)
package com.imooc.sm.service;

import com.imooc.sm.entity.Staff;

import java.util.List;

public interface StaffService {
    void add(Staff staff);
    void remove(Integer id);
    void edit(Staff staff);
    Staff get(Integer id);
    List<Staff> getAll();
}

  1. com.imooc.sm.service.impl包>新建StaffServiceImpl (业务层实现类)
package com.imooc.sm.service.impl;

import com.imooc.sm.dao.StaffDao;
import com.imooc.sm.entity.Staff;
import com.imooc.sm.service.StaffService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
@Service("staffService")
public class StaffServiceImpl implements StaffService {
@Autowired
    private StaffDao staffDao;

    public void add(Staff staff) {
        staff.setPassword("123456");//设置默认密码
        staff.setWorkTime(new Date());//设置默认入职日期
        staff.setStatus("正常");//设置默认状态
        staffDao.insert(staff);
    }

    public void remove(Integer id) {
        staffDao.delete(id);
    }

    public void edit(Staff staff) {
        staffDao.update(staff);
    }

    public Staff get(Integer id) {
        return staffDao.selectById(id);
    }

    public List<Staff> getAll() {
        return staffDao.selectAll();
    }
}

3.2.3、实现表现层

在sm_web模块下

  1. com.imooc.sm.controller包下>新建StaffController(控制器)
package com.imooc.sm.controller;

import com.imooc.sm.entity.Department;
import com.imooc.sm.entity.Staff;
import com.imooc.sm.service.DepartmentService;
import com.imooc.sm.service.StaffService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Controller("staffController")
public class StaffController {
    @Autowired
    private StaffService staffService;
    @Autowired
    private DepartmentService departmentService;

    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Staff> list = staffService.getAll();
        request.setAttribute("LIST",list);
        request.getRequestDispatcher("../staff_list.jsp").forward(request,response);
    }

    public void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Department> list = departmentService.getAll();
        request.setAttribute("DLIST",list);
        request.getRequestDispatcher("../staff_add.jsp").forward(request,response);
    }
    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String account = request.getParameter("account");
        String name = request.getParameter("name");
        String sex = request.getParameter("sex");
        String idNumber = request.getParameter("idNumber");
        String info =request.getParameter("info");
        Date bornDate=null;
        try {//request中接收值为String类型,这里进行String转为java.util.Date
            bornDate = new SimpleDateFormat("yyyy-MM-dd").parse(request.getParameter("bornDate"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Integer did = Integer.parseInt(request.getParameter("did"));

        Staff staff = new Staff();
        staff.setInfo(info);
        staff.setBornDate(bornDate);
        staff.setIdNumber(idNumber);
        staff.setDid(did);
        staff.setAccount(account);
        staff.setName(name);
        staff.setSex(sex);

        staffService.add(staff);
        response.sendRedirect("list.do");
    }

    public void toEdit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        Staff staff = staffService.get(id);
        request.setAttribute("OBJ",staff);
        List<Department> list = departmentService.getAll();
        request.setAttribute("DLIST",list);
        request.getRequestDispatcher("../staff_edit.jsp").forward(request,response);
    }
    public void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        String account = request.getParameter("account");
        String name = request.getParameter("name");
        String sex = request.getParameter("sex");
        String idNumber = request.getParameter("idNumber");
        String info =request.getParameter("info");
        Date bornDate=null;
        try {
            bornDate = new SimpleDateFormat("yyyy-MM-dd").parse(request.getParameter("bornDate"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Integer did = Integer.parseInt(request.getParameter("did"));

        Staff staff = staffService.get(id);
        staff.setInfo(info);
        staff.setBornDate(bornDate);
        staff.setIdNumber(idNumber);
        staff.setDid(did);
        staff.setAccount(account);
        staff.setName(name);
        staff.setSex(sex);
//        在完成3.3.3节后打开注释
//        /**由于staff是之前数据库中查询出来的,department属性没有修改,只修改了did属性
//         * 所以,我们把department根据did属性查询出来并设置给staff的department属性*/
//        Department department = departmentService . get(did);
//        staff.setDepartment (department);
//        //判断一下, 如果当前修改的用户与当前登录的用户是同一个,把修改后的用户放到session 中
//        Staff staff1 = (Staff) request. getSession(). getAttribute("USER");
//        if(staff1. getId().equals(staff.getId())){
//            request.getSession(). setAttribute("USER" ,staff);
//        }
        staffService.edit(staff);
        response.sendRedirect("list.do");
    }
    public void remove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        staffService.remove(id);
        response.sendRedirect("list.do");
    }

    public void detail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Integer id = Integer.parseInt(request.getParameter("id"));
        Staff staff = staffService.get(id);
        request.setAttribute("OBJ",staff);
        request.getRequestDispatcher("../staff_detail.jsp").forward(request,response);
    }
}

JSP页面的编码,我就不放出来了,现在基本不会在使用JSP,该项目只是为了演示Spring+Mybatis+Servlet案例,大家可以自行通过案例源码下载查看

3.3、登录与个人中心

实现登陆、退出、个人信息、修改密码

关注点

  • Session操作
  • 登陆过滤器

步骤

  • 实体类(就是3.2中定义的staff实体类)
  • Dao接口与Sql映射文件
  • Service接口与其实现类
  • 控制器
  • 页面

3.3.1、实现持久层

在sm_service模块下

因实体类就是3.2中定义的staff实体类,故直接定义dao

  1. 在java文件夹下>com.imooc.sm.dao包下>新建StaffDao (持久化操作接口)
package com.imooc.sm.dao;

import com.imooc.sm.entity.Staff;
import org.springframework.stereotype.Repository;

@Repository("selfDao")
public interface SelfDao {
    Staff selectByAccount(String account);
}

  1. 创建映射文件SelfDao.xml
    在resources下com/imooc/sm/dao文件夹>创建映射文件SelfDao.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.sm.dao.SelfDao">

    <select id="selectByAccount" parameterType="String" resultMap="com.imooc.sm.dao.StaffDao.resultMap">
        select * from staff where account=#{account}
    </select>

</mapper>

3.3.2、实现业务层

在sm_service模块下

  1. 在com.imooc.sm.service包下>新建SelfService (业务层接口)
package com.imooc.sm.service;

import com.imooc.sm.entity.Staff;

public interface SelfService {
    Staff login(String account, String password);
    void changePassword(Integer id,String password);
}

  1. com.imooc.sm.service.impl包>新建SelfServiceImpl (业务层实现类)
package com.imooc.sm.service.impl;

import com.imooc.sm.dao.SelfDao;
import com.imooc.sm.dao.StaffDao;
import com.imooc.sm.entity.Staff;
import com.imooc.sm.service.SelfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("selfService")
public class SelfServiceImpl implements SelfService {
    @Autowired
    private SelfDao selfDao;
    @Autowired
    private StaffDao staffDao;

    public Staff login(String account, String password) {
        Staff staff =selfDao.selectByAccount(account);
        if(staff==null)return null;
        if(staff.getPassword().equals(password))return staff;
        return null;
    }

    public void changePassword(Integer id, String password) {
        Staff staff = staffDao.selectById(id);
        staff.setPassword(password);
        staffDao.update(staff);
    }
}

3.3.3、实现表现层

在sm_web模块下

  1. com.imooc.sm.global包下>新建LoginFilter (登陆过滤器)
package com.imooc.sm.global;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request=(HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        //获取访问路径
        String path = request.getServletPath();

        if(path.toLowerCase().indexOf("login")!=-1){
            filterChain.doFilter(request,response);
        }else{
            HttpSession session = request.getSession();
            Object obj =session.getAttribute("USER");
            if(obj!=null){
                filterChain.doFilter(request,response);
            }else{//getContextPath获取请求上下文
                response.sendRedirect(request.getContextPath()+"/toLogin.do");
            }
        }
    }

    public void destroy() {
    }
}
  1. com.imooc.sm.controller包下>新建SelfController (控制器)
package com.imooc.sm.controller;

import com.imooc.sm.entity.Staff;
import com.imooc.sm.service.SelfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@Controller("selfController")
public class SelfController {
    @Autowired
    private SelfService selfService;

    //实现打开登录界面功能,访问路径:/toLogin.do
    public void toLogin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("login.jsp").forward(request,response);
    }
    //实现登录功能,路径:/login.do
    public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String account =request.getParameter("account");
        String password = request.getParameter("password");

        Staff staff = selfService.login(account,password);
        if(staff==null){
            response.sendRedirect("toLogin.do");
        }else{
            HttpSession session = request.getSession();
            session.setAttribute("USER",staff);
            response.sendRedirect("main.do");
        }
    }
    //实现退出功能,路径:/logout.do
    public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.setAttribute("USER", null);
        response.sendRedirect("toLogin.do");
    }
    //实现打开主界面功能,访问路径:/main.do
    public void main(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("index.jsp").forward(request,response);
    }
    //实现打开个人信息界面功能,访问路径:/self/info.do
    public void info(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("../info.jsp").forward(request,response);
    }
    //实现打开修改密码界面功能,访问路径:/self/toChangePassword.do
    public void toChangePassword(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("../change_password.jsp").forward(request,response);
    }
    //实现修改密码功能,访问路径:/self/changePassword.do
    public void changePassword(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String password = request.getParameter("password");
        String password1 = request.getParameter("password1");
        HttpSession session = request.getSession();
        Staff staff = (Staff)session.getAttribute("USER");
        if(!staff.getPassword().equals(password)){
            response.sendRedirect("toChangePassword.do");
        }else{
            selfService.changePassword(staff.getId(),password1);
            //response.sendRedirect("../logout.do");
            //使用javascript使父窗口跳转../logout.do
            response.getWriter().print("<script type=\"text/javascript\">parent.location.href=\"../logout.do\"</script>");
        }
    }
}

JSP页面的编码,我就不放出来了,现在基本不会在使用JSP,该项目只是为了演示Spring+Mybatis+Servlet案例,大家可以自行通过案例源码下载查看

3.4、日志处理

实现日志查看、自动记录

关注点

  • 业务功能设计
  • 通知处理

步骤

  • 实体类(就是3.2中定义的staff实体类)
  • Dao接口与Sql映射文件
  • Service接口与其实现类
  • 控制器
  • 页面

3.4.1、实现持久层

在sm_service模块下

  1. 在com.imooc.sm.entity包下>新建Log (实体类)
package com.imooc.sm.entity;

import java.util.Date;

public class Log {
    private Date oprTime;
    private String type;
    private String operator;
    private String moudle;
    private String operation;
    private String result;

    public Date getOprTime() {
        return oprTime;
    }

    public void setOprTime(Date oprTime) {
        this.oprTime = oprTime;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }

    public String getMoudle() {
        return moudle;
    }

    public void setMoudle(String moudle) {
        this.moudle = moudle;
    }

    public String getOperation() {
        return operation;
    }

    public void setOperation(String operation) {
        this.operation = operation;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

  1. 在java文件夹下>com.imooc.sm.dao包下>新建LogDao (持久化操作接口)
package com.imooc.sm.dao;

import com.imooc.sm.entity.Log;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository("logDao")
public interface LogDao {
    void insert(Log log);
    List<Log> selectByType(String type);
}

  1. 创建映射文件LogDao.xml
    在resources下com/imooc/sm/dao文件夹>创建映射文件LogDao.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.imooc.sm.dao.LogDao">
    <resultMap id="resultMap" type="Log">
        <result property="oprTime" column="opr_time" javaType="java.util.Date"/>
        <result property="type" column="type" javaType="String"/>
        <result property="operator" column="operator" javaType="String"/>
        <result property="moudle" column="moudle" javaType="String"/>
        <result property="operation" column="operation" javaType="String"/>
        <result property="result" column="result" javaType="String"/>
     </resultMap>

    <insert id="insert" parameterType="Log">
        insert into log values(#{oprTime},#{type},#{operator},#{moudle},#{operation},#{result});
    </insert>

    <select id="selectByType" parameterType="String" resultMap="resultMap">
        select * from log where type=#{type} order by opr_time desc
    </select>

</mapper>

3.4.2、实现业务层

在sm_service模块下

  1. 在com.imooc.sm.service包下>新建LogService (业务层接口)
package com.imooc.sm.service;

import com.imooc.sm.entity.Log;

import java.util.List;

public interface LogService {
    void addSystemLog(Log log);
    void addLoginLog(Log log);
    void addOperationLog(Log log);

    List<Log> getSystemLog();
    List<Log> getLoginLog();
    List<Log> getOperationLog();
}

  1. com.imooc.sm.service.impl包>新建SelfServiceImpl (业务层实现类)
package com.imooc.sm.service.impl;

import com.imooc.sm.dao.LogDao;
import com.imooc.sm.entity.Log;
import com.imooc.sm.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
@Service("logService")
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;

    public void addSystemLog(Log log) {
        log.setOprTime(new Date());
        log.setType("system");
        logDao.insert(log);
    }

    public void addLoginLog(Log log) {
        log.setOprTime(new Date());
        log.setType("login");
        logDao.insert(log);
    }

    public void addOperationLog(Log log) {
        log.setOprTime(new Date());
        log.setType("operation");
        logDao.insert(log);
    }

    public List<Log> getSystemLog() {
        return logDao.selectByType("system");
    }

    public List<Log> getLoginLog() {
        return logDao.selectByType("login");
    }

    public List<Log> getOperationLog() {
        return logDao.selectByType("operation");
    }
}

什么时候记录日志?

  • 日志里面需要记录操作员,操作员在web层session中保存,所以处理用户请求的时候,记录日志这是最合理的,也就是在某个控制器方法被调用时,我们去调用记录日志的功能
  • 但是记录日志的代码不能写在被调用的控制器方法中,第一是要记录日志的方法太多,工作量太大,第二被调永的控制器方法是为了处理用户的某种请求,与记录日志没有本质关系
  • 所以记录日志应该使用切面处理,然后自动注入

在sm_web模块下
3. com.imooc.sm.global包下>新建LogAdvice (切面类)

package com.imooc.sm.global;

import com.imooc.sm.entity.Log;
import com.imooc.sm.entity.Staff;
import com.imooc.sm.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Component
@Aspect
public class LogAdvice {
    @Autowired
    private LogService logService;

    // && !表示去除
    @AfterReturning("execution(* com.imooc.sm.controller.*.*(..)) && !execution(* com.imooc.sm.controller.SelfController.*(..)) && !execution(* com.imooc.sm.controller.*.to*(..))")
    public void operationLog(JoinPoint joinPoint){
        Log log = new Log();

        //JoinPoint连接点对象,用来获得切点所在类与切点方法名,直接输出为切点方法名称(全路径)
        //获取切点所在类的类名(获取当前操作的模块)
        log.setMoudle(joinPoint.getTarget().getClass().getSimpleName());

        //获取切点方法名称(获取当前进行的操作名称)
        log.setOperation(joinPoint.getSignature().getName());

        //获取当前当前操作人
        //joinPoint.getArgs()[0]获取获取当前切点操作的request
        HttpServletRequest request =(HttpServletRequest) joinPoint.getArgs()[0];
        HttpSession session = request.getSession();
        Object obj = session.getAttribute("USER");
        Staff staff =(Staff)obj;
        log.setOperator(staff.getAccount());
        log.setResult("成功");
        logService.addOperationLog(log);
    }
    @AfterThrowing(throwing ="e",pointcut ="execution(* com.imooc.sm.controller.*.*(..)) && !execution(* com.imooc.sm.controller.SelfController.*(..))")
    public void systemLog(JoinPoint joinPoint,Throwable e){
        Log log = new Log();
        log.setMoudle(joinPoint.getTarget().getClass().getSimpleName());
        log.setOperation(joinPoint.getSignature().getName());
        HttpServletRequest request =(HttpServletRequest) joinPoint.getArgs()[0];
        HttpSession session = request.getSession();
        Object obj = session.getAttribute("USER");
        Staff staff =(Staff)obj;
        log.setOperator(staff.getAccount());
        log.setResult(e.getClass().getSimpleName());
        logService.addSystemLog(log);
    }

    @After("execution(* com.imooc.sm.controller.SelfController.login(..))")
    public void loginLog(JoinPoint joinPoint){
        log(joinPoint);
    }


    @Before("execution(* com.imooc.sm.controller.SelfController.logout(..))")
    public void logoutLog(JoinPoint joinPoint){
        log(joinPoint);
    }

    private void log(JoinPoint joinPoint){
        Log log = new Log();
        log.setMoudle(joinPoint.getTarget().getClass().getSimpleName());
        log.setOperation(joinPoint.getSignature().getName());
        HttpServletRequest request =(HttpServletRequest) joinPoint.getArgs()[0];
        HttpSession session = request.getSession();
        Object obj = session.getAttribute("USER");
        if(obj==null){
            log.setOperator(request.getParameter("account"));
            log.setResult("失败");
        }else {
            Staff staff = (Staff) obj;
            log.setOperator(staff.getAccount());
            log.setResult("成功");
        }
        logService.addLoginLog(log);
    }
}

3.4.3、实现表现层

在sm_web模块下

  1. com.imooc.sm.controller包下>新建LogController (控制器)
package com.imooc.sm.controller;

import com.imooc.sm.entity.Department;
import com.imooc.sm.entity.Log;
import com.imooc.sm.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Controller("logController")
public class LogController {
    @Autowired
    private LogService logService;

    public void operationLog(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Log> list = logService.getOperationLog();
        request.setAttribute("LIST",list);
        request.setAttribute("TYPE","操作");
        request.getRequestDispatcher("../log_list.jsp").forward(request,response);
    }

    public void loginLog(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Log> list = logService.getLoginLog();
        request.setAttribute("LIST",list);
        request.setAttribute("TYPE","登陆");
        request.getRequestDispatcher("../log_list.jsp").forward(request,response);
    }

    public void systemLog(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Log> list = logService.getSystemLog();
        request.setAttribute("LIST",list);
        request.setAttribute("TYPE","系统");
        request.getRequestDispatcher("../log_list.jsp").forward(request,response);
    }
}

JSP页面的编码,我就不放出来了,现在基本不会在使用JSP,该项目只是为了演示Spring+Mybatis+Servlet案例,大家可以自行通过案例源码下载查看

到这里该项目就结束了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翘脚猴子耍把戏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值