Maven学习(七)Maven工程单一架构案例

单一架构案例

  • 一、创建工程,引入依赖
    • 1.架构
      • ①架构的概念
      • ②单一架构
    • 2.创建工程
    • 3. 引入依赖
      • ①搜索依赖信息的网站
      • ②持久化层所需依赖
      • ③表示层所需依赖
      • ④辅助功能所需依赖
      • ⑤最终完整依赖信息
    • 4.建包
  • 二、搭建环境:持久化层
    • 1.数据建模
      • ①物理建模
      • ②逻辑建模
    • 2.数据库连接信息
    • 3.获取数据库连接
      • ①创建JDBCUtils工具类
      • ②创建javax.sql.DataSource对象
      • ③创建ThreadLocal对象
      • ④声明方法:获取数据库连接
      • ⑤声明方法:释放数据库连接
      • ⑥初步测试
    • 4.BaseDao
      • ①泛型的说明
      • ②测试BaseDao
    • 5.子类Dao
      • ①创建接口和实现类
  • 三、搭建环境:事务控制
    • 1.总体思路
    • 2.TransactionFilter
      • ①创建Filter类
      • ②完整代码
      • ③配置web.xml
      • ④注意点
  • 四、搭建环境:表示层
    • 1.视图模板技术Thymeleaf
      • ①服务器端渲染
      • ③逻辑视图与物理视图
      • ④ViewBaseServlet完整代码
      • ⑤增加前缀后缀的web.xml配置
      • ⑥Thymeleaf页面语法
    • 2.ModelBaseServlet
      • ①提出问题
      • ②解决方案
      • ③完整代码
      • ④继承关系
  • 五、搭建环境:辅助功能
    • 1.常量类
    • 2.MD5加密工具类
      • 3.日志配置文件
  • 六、业务功能:登录
    • 1.显示首页
      • ① 流程图
      • ②创建PortalServlet
      • ③在index.html中编写登录页面
    • 2.登录操作
      • ①流程图
      • ②编写EmpDao的方法
      • ③创建EmpService类
      • ④创建登录失败异常
      • ⑤增加一个常量
      • ⑥创建AuthServlet类
      • ⑦temp页面
      • ⑧注册,在web.xml中增加信息
      • ⑨运行结果
    • 3.退出登录
      • ①在临时页面编写超链接
      • ②在AuthServlet编写退出的逻辑
  • 七、业务功能:显示列表
    • 1.流程图
    • 2.创建组件
      • ①创建Java类
      • ② 注册,在web.xml中增加信息
    • 3.页面显示
    • 4.和登录对接
  • 八、业务功能:显示详情
    • 1.详情页代码
    • 2.workServlet方法
    • 3.MemorialsService方法
    • 4.MemorialsServiceImpl方法增加
    • 5.MemorialsDao方法
    • 5.MemorialsDaoImpl方法
    • 6. 结果图展示
  • 九、业务功能:回复
    • 1.WorkServlet方法
    • 2.MemorialsService方法
    • 3.MemorialsServiceImpl方法
    • 4.MemorialsDao方法
    • 5.MemorialsDaoImpl方法
  • 十、业务功能:登录检查
    • 1.逻辑
    • 2.创建LoginFilter
    • 3.配置web.xml
  • 十一、打包部署
    • 1.适配环境信息
    • 2.跳过测试打包
    • 3.上传war包
    • 4.启动Tomcat
    • 5.访问测试

本章节将以创建一个单一架构的业务系统,从搭建到部署的过程,演示Maven项目
完整代码gitee地址:https://gitee.com/reportories/maven_study_all_in_one.git

一、创建工程,引入依赖

1.架构

①架构的概念

架构其实就是项目的结构,只是因为架构是一个更大的词,通常来形容比较大规模事物的结构。

②单一架构

单一架构也叫all-in-one的结构,就是所有的代码、配置文件、各种资源都在同一个工程

  • 一个项目包含一个工程
  • 导出一个war包
  • 放在一个Tomcat上运行

2.创建工程

Maven学习(七)Maven工程单一架构案例_第1张图片
Maven学习(七)Maven工程单一架构案例_第2张图片

3. 引入依赖

①搜索依赖信息的网站

【1】 到哪找?

依赖信息网站

【2】怎么选择?

  • 确定技术选型:确定我们项目中要使用哪些技术
  • 到网站去搜索具体技术的依赖信息
  • 确定这个技术使用哪个版本的依赖
    • 考虑因素1:看是否有别的技术要求这里必须使用某一个版本
    • 考虑因素2:如果没有硬性要求,那么选择较高版本或者下载量的版本
  • 在实际使用中检验所有依赖信息是否都正常可用

tips:
确定技术选型、组件依赖列表,项目划分模块等操作都是属于架构设计的范围。

  • 项目本身所属行业的基本特点
  • 项目具体的功能需求
  • 项目预计访问压力程度
  • 项目预计将来需要扩展的功能

②持久化层所需依赖

首先确保自己本机已经安装了mysql数据库,安装过程不再赘述。
mysql依赖


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <version>8.0.28version>
dependency>

druid依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druidartifactId>
    <version>1.2.8version>
dependency>


<dependency>
    <groupId>commons-dbutilsgroupId>
    <artifactId>commons-dbutilsartifactId>
    <version>1.7version>
dependency>

③表示层所需依赖


<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>javax.servlet-apiartifactId>
    <version>3.1.0version>
    <scope>providedscope>
dependency>


<dependency>
    <groupId>org.thymeleafgroupId>
    <artifactId>thymeleafartifactId>
    <version>3.0.11.RELEASEversion>
dependency>

④辅助功能所需依赖


<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <version>4.12version>
    <scope>testscope>
dependency>


<dependency>
    <groupId>ch.qos.logbackgroupId>
    <artifactId>logback-classicartifactId>
    <version>1.2.3version>
    <scope>testscope>
dependency>

⑤最终完整依赖信息

 <dependencies>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.28version>
        dependency>

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.2.8version>
        dependency>

        <dependency>
            <groupId>commons-dbutilsgroupId>
            <artifactId>commons-dbutilsartifactId>
            <version>1.7version>
        dependency>

        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
            <scope>providedscope>
        dependency>

        <dependency>
            <groupId>org.thymeleafgroupId>
            <artifactId>thymeleafartifactId>
            <version>3.0.11.RELEASEversion>
        dependency>

        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>
    dependencies>

4.建包

package功能 package名称
主包 com.sr.maven
子包【实体类】 com.sr.maven.entity
子包 【servlet基类包】 com.sr.maven.servlet.base
子包 【servelet模块包】 com.sr.maven.servlet.module
子包 【servlet接口包】 com.sr.maven.servlet.api
子包 【servlet实现类包】 com.sr.maven.servlet.imp
子包 【Dao接口包】 com.sr.maven.dao.api
子包 【Dao实现类包】 com.sr.maven.dao.imp
子包【Filter过滤器包】 com.sr.maven.filter
子包 【异常类包】 com.sr.maven.exception
子包 【工具类包】 com.sr.maven.util
子包 【测试类包】 com.sr.maven.test

Maven学习(七)Maven工程单一架构案例_第3张图片

二、搭建环境:持久化层

1.数据建模

①物理建模

在mysql数据库运行sql语句,进行物理建模,建表

CREATE DATABASE db_imperial_court;
USE db_imperial_court;
CREATE TABLE t_emp (
	emp_id INT PRIMARY KEY auto_increment,
	emp_name CHAR ( 100 ) NOT NULL,
	emp_position CHAR ( 100 ) NOT NULL,
	login_account CHAR ( 100 ) NOT NULL UNIQUE,
	login_password CHAR ( 100 ) NOT NULL 
);
INSERT INTO t_emp ( emp_name, emp_position, login_account, login_password )
VALUES# 16540504
( '爱新觉罗.玄烨', 'emperor', 'xiaoxuanzi1654', '25325c896624D444B2E241807DCAC988' ),
( '纳兰明珠', 'minister', 'brightba771635', '25325c896624D444B2E241807DCAC988' ),
( '赫舍里.索额图', 'minister', 'tutu1636', '25325c896624D444B2E241807DCAC988' );
CREATE TABLE t_memorials (
	memorials_id INT PRIMARY KEY auto_increment,
	memorials_title CHAR ( 100 ) NOT NULL,
	memorials_content VARCHAR ( 5000 ) NOT NULL,
	memorials_emp INT NOT NULL,
	memorials_create_time CHAR ( 100 ),
	feedback_time CHAR ( 100 ),
	feedback_content VARCHAR ( 1000 ),
	memorials_status INT NOT NULL 
);
INSERT INTO t_memorials ( memorials_title, memorials_content, memorials_emp, memorials_create_time, feedback_time, feedback_content, memorials_status )
VALUES# 16540504
( '浙江巡抚奏钱塘江堤决口疏', '皇上啊,不好了!钱塘江发大水啦!堤坝冲毁啦!您看咋弄啊!', 2, '1690-05-07', NULL, NULL, 0 ),
( '左都御史参鳌拜圈地口疏', '皇上啊,鳌拜这厮不是东西啊!占老百姓的地呀,还打人呀!您看咋弄啊', 3, '1690-04-14', NULL, NULL, 0 ),
( '督察员参吴三桂不臣疏', '皇上啊,不好了!吴三桂那孙子想造反!', 2, '1693-11-18', NULL, NULL, 0 ),
( '兵部奏准噶尔犯境疏', '皇上啊,不好了!噶尔丹要打过来了!', 3, '1693-11-18', NULL, NULL, 0 );

②逻辑建模

【1】Emp实体类

package com.sr.maven.entity;

public class Emp {

    private Integer empId;

    private String empName;

    private String empPosition;

    private String loginAccount;

    private String loginPassword;


    public Emp() {
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpPosition() {
        return empPosition;
    }

    public void setEmpPosition(String empPosition) {
        this.empPosition = empPosition;
    }

    public String getLoginAccount() {
        return loginAccount;
    }

    public void setLoginAccount(String loginAccount) {
        this.loginAccount = loginAccount;
    }

    public String getLoginPassword() {
        return loginPassword;
    }

    public void setLoginPassword(String loginPassword) {
        this.loginPassword = loginPassword;
    }
}

【2】Memorials实体类

public class Memorials {


    private Integer memorialsId;

    private String memorialsTitle;

    private String memorialsContent;

    private String memorialsContentDigest;

    private Integer memorialsEmp;

    private String memorialsEmpEmpName;

    private String memorialsCreateTime;

    private String feedbackTime;

    private String feedbackContent;

    private Integer memorialsStatus;


    public Memorials() {
    }

    public Integer getMemorialsId() {
        return memorialsId;
    }

    public void setMemorialsId(Integer memorialsId) {
        this.memorialsId = memorialsId;
    }

    public String getMemorialsTitle() {
        return memorialsTitle;
    }

    public void setMemorialsTitle(String memorialsTitle) {
        this.memorialsTitle = memorialsTitle;
    }

    public String getMemorialsContent() {
        return memorialsContent;
    }

    public void setMemorialsContent(String memorialsContent) {
        this.memorialsContent = memorialsContent;
    }

    public String getMemorialsContentDigest() {
        return memorialsContentDigest;
    }

    public void setMemorialsContentDigest(String memorialsContentDigest) {
        this.memorialsContentDigest = memorialsContentDigest;
    }

    public Integer getMemorialsEmp() {
        return memorialsEmp;
    }

    public void setMemorialsEmp(Integer memorialsEmp) {
        this.memorialsEmp = memorialsEmp;
    }

    public String getMemorialsEmpEmpName() {
        return memorialsEmpEmpName;
    }

    public void setMemorialsEmpEmpName(String memorialsEmpEmpName) {
        this.memorialsEmpEmpName = memorialsEmpEmpName;
    }

    public String getMemorialsCreateTime() {
        return memorialsCreateTime;
    }

    public void setMemorialsCreateTime(String memorialsCreateTime) {
        this.memorialsCreateTime = memorialsCreateTime;
    }

    public String getFeedbackTime() {
        return feedbackTime;
    }

    public void setFeedbackTime(String feedbackTime) {
        this.feedbackTime = feedbackTime;
    }

    public String getFeedbackContent() {
        return feedbackContent;
    }

    public void setFeedbackContent(String feedbackContent) {
        this.feedbackContent = feedbackContent;
    }

    public Integer getMemorialsStatus() {
        return memorialsStatus;
    }

    public void setMemorialsStatus(Integer memorialsStatus) {
        this.memorialsStatus = memorialsStatus;
    }
}

2.数据库连接信息

Maven学习(七)Maven工程单一架构案例_第4张图片
编写自己的数据库配置

driverClassName=com.mysql.cj.jdbc.Driver
url= jdbc:mysql://localhost:3306/db_imperial_court?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username=自己的账户
password=自己的密码
initialSize=10
maxActive=20
maxWait=10000

3.获取数据库连接

①创建JDBCUtils工具类

Maven学习(七)Maven工程单一架构案例_第5张图片
首先先放出完整的工具类内容,下面进行分步骤的添加解释

package com.sr.maven.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 功能1:从数据源获取数据库链接
 * 功能2:将数据源获取到数据库连接绑定到本地线程 ThreadLocal
 * 功能3:释放线程时和本地超线程解除绑定
 */
public class JDBCUtils {

    //数据源成员变量,设置为静态资源,保证大对象的单例性,同时保证静态方法中可以访问
    private static DataSource dataSource;

    //由于ThreadLocal对象需要作为绑定数据时K-v对中的key,所以需要保证唯一性
    //加static声明为静态资源可保证唯一性
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    //在静态代码块中初始化数据源
    static {

        try {
            //从jdbc.properties中读取链接数据库的信息
            //为了保证程序代码的可移植性,需要基于一个确定的基准来读取这个文件
            //确定的基准,类路径的根目录,resource目录下的内容经过构建后打包操作会确定放在 WEB-INF/classes目录下。
            //WEB-INF/classes 目录存放编译好的*.class字节码文件,所以这个目录我们就称之为类路径
            //类路径无论是在本地运行还是在服务器端运行都是一个确定的路径
            //具体操作代码
            //1.获取当前类的类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            //2.通过类加载器对象从类路径根目录下读取文件
            InputStream stream = classLoader.getResourceAsStream("jdbc.properties");
            //3.使用Properties类封装属性文件中的数据
            Properties properties = new Properties();
            properties.load(stream);
            //4.根据Properties对象(已经封装了数据库连接信息)来创建数据源对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            //为了避免在真正抛出异常后,catch块捕捉获取到异常掩盖问题
            //这里将所捕获的异常封装为运行时异常继续抛出去
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() {
        Connection connection;
        try {
            //1.尝试从当前线程检查是否已存在绑定的Connection对象
             connection = threadLocal.get();
            //2.检查Connection对象是否为null
            if (connection == null) {
                connection = dataSource.getConnection();

                //绑定到当前线程
                threadLocal.set(connection);
            }
        }catch (SQLException e){
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
        return connection;
    }


    public static void  releaseConnection(Connection connection){

        if(connection!=null){
            try {
                connection.close();
                threadLocal.remove();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }
}

②创建javax.sql.DataSource对象

    //数据源成员变量,设置为静态资源,保证大对象的单例性,同时保证静态方法中可以访问
    private static DataSource dataSource;
   //在静态代码块中初始化数据源
    static {

        try {
            //从jdbc.properties中读取链接数据库的信息
            //为了保证程序代码的可移植性,需要基于一个确定的基准来读取这个文件
            //确定的基准,类路径的根目录,resource目录下的内容经过构建后打包操作会确定放在 WEB-INF/classes目录下。
            //WEB-INF/classes 目录存放编译好的*.class字节码文件,所以这个目录我们就称之为类路径
            //类路径无论是在本地运行还是在服务器端运行都是一个确定的路径
            //具体操作代码
            //1.获取当前类的类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            //2.通过类加载器对象从类路径根目录下读取文件
            InputStream stream = classLoader.getResourceAsStream("jdbc.properties");
            //3.使用Properties类封装属性文件中的数据
            Properties properties = new Properties();
            properties.load(stream);
            //4.根据Properties对象(已经封装了数据库连接信息)来创建数据源对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            //为了避免在真正抛出异常后,catch块捕捉获取到异常掩盖问题
            //这里将所捕获的异常封装为运行时异常继续抛出去
            throw new RuntimeException(e);
        }
    }

③创建ThreadLocal对象

【1】提出需求
(1)在一个方法内控制事务
如果在每一个Service方法中都写下面的代码,那么代码重复性就太高了

try{
	//1.获取数据连接
	//重要:要保证参与事务的多个数据库操作(SQL语句)使用的是同一个数据库连接
	Connection  conn = JDBCUtils.getConnection();
	//2.核心操作
	//....省略
	
	//3.核心操作陈工结束,可以提交事务
	conn.commit();
}catch(Exception e){
	//4 核心操作抛出异常,必须回滚事务
	conn.rollback();
}finally{
	//5.释放数据库连接
	JDBCUtils.releaseConnection(conn);
}

(2)将重复的代码抽取到Filter中
所谓当前请求覆盖的Servlet方法、Service方法、Dao方法就是chain.doFilter间接调用的方法。

public void doFilter(ServletRequest request,ServlertResponse response ,FilterChain chain){
	try{
		//1.获取数据连接
		//重要:要保证参与事务的多个数据库操作(SQL语句)使用的是同一个数据库连接
		Connection  conn = JDBCUtils.getConnection();
		  //关闭自动提交
            connection.setAutoCommit(false);
		//2.核心操作:通过chain对象放行当前请求
		//这样就可以保证当前请求覆盖的Servlet方法、Service方法、Dao方法都在同一个事务中
		//同时各个请求都经过这个Filter,所以当前事务控制的代码这里只写了一遍
		//避免了代码的冗余
		chain.doFilter(request,response);
		//3.核心操作陈工结束,可以提交事务
		conn.commit();
	}catch(Exception e){
		//4 核心操作抛出异常,必须回滚事务
		conn.rollback();
	}finally{
		//5.释放数据库连接
		JDBCUtils.releaseConnection(conn);
	}
}

(3)数据的跨方法传递
但是,通过(2),我们还是会遇到一个难题,如图所示,为了保证使用同一个数据库连接对象,但是chain.doFilter方法又无法传参,我们该怎么办?
通过JDBCUtils工具类获取的Connection对象需要传递给Dao方法,让事务涉及到的所有Dao方法用的都是同一个Connection对象。
但是Connection对象无法通过chain.doFilter()方法以参数的形式传递。以下所有方法调用都是在同一线程内。
Maven学习(七)Maven工程单一架构案例_第6张图片
【2】ThreadLocal对象的功能
Maven学习(七)Maven工程单一架构案例_第7张图片

  • 全类名:java.lang.ThreadLocal
  • 泛型T:要绑定到当前线程的类型
  • 三个主要的方法
方法名 功能
set(T value) 将数据绑定到当前线程
get() 从当前线程获取已绑定的数据
remove 将数据从当前线程移除

【3】Java代码

//由于ThreadLocal对象需要作为绑定数据时K-v对中的key,所以需要保证唯一性
//加static声明为静态资源可保证唯一性
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

④声明方法:获取数据库连接

 public static Connection getConnection() {
        Connection connection;
        try {
            //1.尝试从当前线程检查是否已存在绑定的Connection对象
             connection = threadLocal.get();
            //2.检查Connection对象是否为null
            if (connection == null) {
                connection = dataSource.getConnection();

                //绑定到当前线程
                threadLocal.set(connection);
            }
        }catch (SQLException e){
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
        return connection;
    }

⑤声明方法:释放数据库连接

   public void releaseConnection(Connection connection){

        if(connection!=null){
            try {
                connection.close();
                threadLocal.remove();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    }

⑥初步测试

我们创建一个测试类,看能否正常获取到连接,如下图所示,结果显示正常。
Maven学习(七)Maven工程单一架构案例_第8张图片

public class ImperialCourtTest {
    @Test
    public void testGetConnection(){
        Connection connection = JDBCUtils.getConnection();
        System.out.println("connection = "+connection);
        JDBCUtils.releaseConnection(connection);
    }
}

4.BaseDao

Maven学习(七)Maven工程单一架构案例_第9张图片

①泛型的说明

Maven学习(七)Maven工程单一架构案例_第10张图片

/**
 * BaseDao类:所有Dao类实现类的基类
 * @param  实体类的类型
 */
public class BaseDao<T> {

    //DBUtils 工具包提供的数据操作对象
    private QueryRunner runner = new QueryRunner();

    /**
     * 查询单个对象
     * @param sql sql语句
     * @param entityBean 实体类对象
     * @param parameters 传给sql语句的参数
     * @return 查询到的实体类对象
     */
    public T getSingleBean(String sql ,Class<T> entityBean,Object ... parameters){

        //获取数据库连接
        Connection connection = JDBCUtils.getConnection();
        try {
           return runner.query(connection,sql,new BeanHandler<>(entityBean),parameters);
        } catch (SQLException e) {
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
    }


    /**
     * 查询多个对象
     * @param sql sql语句
     * @param entityBean 实体类对象
     * @param parameters 传给sql语句的参数
     * @return 查询到的实体类对象
     */
    public List<T> getBeanList(String sql , Class<T> entityBean, Object ... parameters){

        //获取数据库连接
        Connection connection = JDBCUtils.getConnection();
        try {
            return runner.query(connection,sql,new BeanListHandler<>(entityBean),parameters);
        } catch (SQLException e) {
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
    }


    public int update (String sql ,Object ... parameters){

        try{
            Connection connection = JDBCUtils.getConnection();
            return runner.update(connection,sql,parameters);
        }catch (SQLException e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }
}

②测试BaseDao

运行显示,结果正常。

public class ImperialCourtTest {

    private BaseDao<Emp> baseDao = new BaseDao<>();

    @Test
    public void testGetConnection(){

        Connection connection = JDBCUtils.getConnection();

        System.out.println("connection = "+connection);
        JDBCUtils.releaseConnection(connection);
    }

    @Test
    public void testGetSingleBean(){

        String sql = "select emp_id empId,emp_name empName,emp_position empPosition,login_account loginAccount,login_password  loginPassword from t_emp where emp_id = ?";

        Emp singleBean = baseDao.getSingleBean(sql, Emp.class, 1);
        System.out.println(singleBean);
    }


    @Test
    public void testGeteBeanList(){

        String sql = "select emp_id empId,emp_name empName,emp_position empPosition,login_account loginAccount,login_password  loginPassword from t_emp ";

        List<Emp> beanList = baseDao.getBeanList(sql, Emp.class);
        beanList.forEach(i->
                System.out.println(i.toString())
        );
    }

    @Test
    public void testUpdate(){

        String sql = "update t_emp set emp_position = ? where emp_id = ?";

        String empPosition = "emperor";

        String empId = "3";

        int affectRow = baseDao.update(sql,empPosition,empId);

        System.out.println("affectRow = "+affectRow);

    }
}

5.子类Dao

①创建接口和实现类

Maven学习(七)Maven工程单一架构案例_第11张图片
EmpDao

public interface EmpDao  {
}

EmpDaoImpl


public class EmpDaoImpl  extends BaseDao<Emp> implements EmpDao {
}

MemorialsDao


public interface MemorialsDao {
}

MemorialsDaoImpl

public class MemorialsDaoImpl extends BaseDao<Memorials> implements MemorialsDao {
}

三、搭建环境:事务控制

1.总体思路

按照先前操作的代码和思路,总结如下:
Maven学习(七)Maven工程单一架构案例_第12张图片

2.TransactionFilter

①创建Filter类

Maven学习(七)Maven工程单一架构案例_第13张图片

②完整代码

package com.sr.maven.filter;

import com.sr.maven.util.JDBCUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

public class TransactionFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    //声明一个集合保存静态资源扩展名,非操作sql的 请求进入到这个过滤器 会浪费性能
    private static  Set<String> staticResourceExNameSet;

    static {

        staticResourceExNameSet = new HashSet<>();
        staticResourceExNameSet.add(".png");
        staticResourceExNameSet.add(".jpg");
        staticResourceExNameSet.add(".js");
        staticResourceExNameSet.add(".css");
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //前置操作,排除静态资源
       HttpServletRequest request = (HttpServletRequest)servletRequest;
       String servletPath = request.getServletPath();
       if(servletPath.contains(".")){
       String extName = servletPath.substring(servletPath.lastIndexOf("."));

       if(staticResourceExNameSet.contains(extName)){
           //如果检测到当前请求确实是静态资源,则直接方形,不做事务操作
           filterChain.doFilter(servletRequest,servletResponse);
           return;
       }
       }
        //1.获取数据库连接
        Connection connection =null;
       //
        try {
            connection = JDBCUtils.getConnection();
            //关闭自动提交
            connection.setAutoCommit(false);
            //2.核心操作
            filterChain.doFilter(servletRequest,servletResponse);
            //3.提交事务
            connection.commit();

        }catch (Exception e){
            try {
                //4.回滚事务
                assert connection != null;
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            //页面显示:将这里捕获到的异常发送到指定页面
            String message = e.getMessage();
            request.setAttribute("message",message);
            request.getRequestDispatcher("/").forward(request,servletResponse);
        }
        finally {
            JDBCUtils.releaseConnection(connection);
        }
    }

    @Override
    public void destroy() {

    }
}

③配置web.xml

Maven学习(七)Maven工程单一架构案例_第14张图片
Maven学习(七)Maven工程单一架构案例_第15张图片

Maven学习(七)Maven工程单一架构案例_第16张图片
web.xml中增加过滤器配置

    <filter>
        <filter-name>txFilterfilter-name>
        <filter-class>com.sr.maven.filter.TransactionFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>txFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>

④注意点

【1】确保异常回滚
在程序执行的过程中,必须让所有的catch块把编译时异常转成运行时异常抛出,否则,Filter捕获不到就无法回滚。
【2】谨防数据库连接提前释放
由于诸多操作都是在使用同一个数据库连接,中间任何一个环节释放数据库连接都会导致后续操作无法正常完成。

四、搭建环境:表示层

1.视图模板技术Thymeleaf

①服务器端渲染

Maven学习(七)Maven工程单一架构案例_第17张图片
②简要的工作机制
【1】初始化阶段

  • 目标:创建TemplateEngine对象
  • 封装:因为对每一个请求来说,TemplateEngine对象使用的都是同一个,所以在初始化阶段准备好。

Maven学习(七)Maven工程单一架构案例_第18张图片
【2】请求处理阶段
Maven学习(七)Maven工程单一架构案例_第19张图片

③逻辑视图与物理视图

假设有如下页面地址:

/WEB-INF/pages/apple.html
/WEB-INF/pages/banana.html
/WEB-INF/pages/orange.html
/WEB-INF/pages/grape.html
/WEB-INF/pages/egg.html

这样的地址可以直接访问到页面本身,我们称之为:物理视图。而将物理视图中前面,后面的固定内容抽取出来,让每次请求指定中间变化部分即可,那么中间变化部分就叫:逻辑视图
Maven学习(七)Maven工程单一架构案例_第20张图片

④ViewBaseServlet完整代码

Maven学习(七)Maven工程单一架构案例_第21张图片
为了简化视图页面的处理过程,封装一个基类,以后具体业务直接继承就好。

package com.sr.maven.servlet.base;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

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

public class ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;


    @Override
    public void init() throws ServletException {

        //1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
        //给解析器对象设置参数
        templateResolver.setTemplateMode(TemplateMode.HTML);
        //设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");
        templateResolver.setPrefix(viewPrefix);

        //设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");
        templateResolver.setSuffix(viewSuffix);

        //设置缓存过期时间
        templateResolver.setCacheTTLMs(600000L);
        templateResolver.setCacheable(true);
        //设置服务器编码格式
        templateResolver.setCharacterEncoding("utf-8");

        //创建模板引擎对象
        templateEngine = new TemplateEngine();
        //给模板引擎设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);
    }

    public void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse res) throws IOException {

        //1.设置响应体内容类型和字符集
        res.setContentType("text/html;charset=UTF-8");
        //2.创建WebContext对象
        WebContext webContext = new WebContext(req,res,getServletContext());
        //3.处理模板数据
        templateEngine.process(templateName,webContext,res.getWriter());
    }
}

⑤增加前缀后缀的web.xml配置


    <context-param>
        <param-name>view-prefixparam-name>
        <param-value>/WEB-INF/pages/param-value>
    context-param>
    <context-param>
        <param-name>view-suffixparam-name>
        <param-value>.html/param-value>
    context-param>

⑥Thymeleaf页面语法

详细去看官网文档就可以

2.ModelBaseServlet

①提出问题

【1】我们的需求
Maven学习(七)Maven工程单一架构案例_第22张图片
【2】HttpServlet的局限

  • doGet()方法:处理Get请求
  • doPost()方法:处理Post请求

②解决方案

  • 每个请求附带一个请求参数,表明自己要调用的目标方法
  • Servlet根据目标方法通过反射调用目标方法

③完整代码

package com.sr.maven.servlet.base;


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

public class ModelBaseServlet extends ViewBaseServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.在所有的request.getParameter()前面设置解析请求体的字符集
        req.setCharacterEncoding("UTF-8");

        //2.从请求参数中获取method对应的数据
        String method = req.getParameter("method");

        //3。通过反射调用method对应的方法
        //这里使用this. 是获取的子类的类型,因为真正执行的时候 是走的子类
        Class<? extends ModelBaseServlet> clazz = this.getClass();

        try{
            //获取method对应的Method对象
            Method methodObject = clazz.getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class);

            //打开访问权限
            methodObject.setAccessible(true);

            //通过method调用方法
            methodObject.invoke(this,req,resp);

        }catch (Exception e){
            e.printStackTrace();
            throw  new RuntimeException(e);
        }
    }
}

④继承关系

Maven学习(七)Maven工程单一架构案例_第23张图片

五、搭建环境:辅助功能

1.常量类

Maven学习(七)Maven工程单一架构案例_第24张图片

package com.sr.maven.util;

public class ImperialCourtConst {

    private static  final String LOGIN_FAIL_MESSAGE = "帐号、密码错误,不可进宫!";


    private static  final String ACCESS_DENIED_MESSAGE = "宫闱禁地,不可擅入!";
}

2.MD5加密工具类

Maven学习(七)Maven工程单一架构案例_第25张图片

package com.sr.maven.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {

    public static String encode(String source) {
        //1.判断明文字符串是否有效
        if (source == null || "".equals(source)) {
            throw new RuntimeException("用于加密的明文不可为空");
        }
        //2.声明算法名称
        String algorithm = "md5";
        //3.获取MessageDigest对象
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        //4. 获取明文字符串对应的字节数组
        byte[] input = source.getBytes();
        //5.执行加密
        byte[] output = messageDigest.digest(input);
        //6.创建BigInter对象
        int signum =1 ;
        BigInteger bigInteger = new BigInteger(signum,output);
        //7.按照16进制将BigInteger的值转换为字符串
        int radix = 16;
        return bigInteger.toString(radix).toUpperCase();

    }
}

3.日志配置文件

Maven学习(七)Maven工程单一架构案例_第26张图片


<configuration debug="true">

    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>

            
            
            <pattern>[%d{HH:mm:ss.SSS}][%-5level][%thread][%logger][%msg]%npattern>
            <charset>UTF-8charset>
        encoder>
    appender>

    
    
    <root level = "INFO">
        
        <appender-ref ref="STDOUT"/>
    root>

    
    <logger name="com.sr" level="DEBUG" additivity="false">
        <appender-ref ref="STDOUT"/>
    logger>
configuration>

六、业务功能:登录

1.显示首页

① 流程图

Maven学习(七)Maven工程单一架构案例_第27张图片

②创建PortalServlet

【1】创建Java类
Maven学习(七)Maven工程单一架构案例_第28张图片

package com.sr.maven.servlet.module;

import com.sr.maven.servlet.base.ViewBaseServlet;

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

public class PortalServlet extends ViewBaseServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //声明要访问的首页的逻辑视图
        String templateName = "index";
        //调用父类的方法根据逻辑视图名称渲染视图
        processTemplate(templateName,req,resp);
    }
}

【2】注册,添加到web.xml中
Maven学习(七)Maven工程单一架构案例_第29张图片

    <servlet>
        <servlet-name>portalServletservlet-name>
        <servlet-class>com.sr.maven.servlet.module.PortalServletservlet-class>
    servlet>
    
    <servlet-mapping>
        <servlet-name>portalServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

③在index.html中编写登录页面

Maven学习(七)Maven工程单一架构案例_第30张图片

DOCTYPE html>
<html lang="en" xml:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>乾清宫title>
head>
<body>
    
    <form th:action="@{auth}" method="post">
        
        <input type="hidden" name="method" value="login"/>
        
        
        <p th:text="${message}">p>
        <p th:text="${systemMessage}">p>

        帐号:<input type="text" name="loginAccount"/><br/>
        帐号:<input type="password" name="loginPassword"/><br/>
        <button type="submit">进宫button>
    form>
body>
html>

2.登录操作

①流程图

Maven学习(七)Maven工程单一架构案例_第31张图片

②编写EmpDao的方法

Maven学习(七)Maven工程单一架构案例_第32张图片

package com.sr.maven.dao.api;

import com.sr.maven.entity.Emp;

public interface EmpDao  {
    Emp selectEmpByLoginAccount(String loginAccount, String loginPassword);
}

Maven学习(七)Maven工程单一架构案例_第33张图片

package com.sr.maven.dao.impl;

import com.sr.maven.dao.BaseDao;
import com.sr.maven.dao.api.EmpDao;
import com.sr.maven.entity.Emp;

public class EmpDaoImpl  extends BaseDao<Emp> implements EmpDao {
    @Override
    public Emp selectEmpByLoginAccount(String loginAccount, String loginPassword) {

        //1.编写sql语句
        String sql = "select emp_id empId,emp_name empName,emp_position empPosition,login_account loginAccount,login_password  loginPassword from t_emp where login_account=? and login_password=?";

        //2.调用父类方法查询单个对象
        return super.getSingleBean(sql, Emp.class, loginAccount,loginPassword);

    }
}

③创建EmpService类

Maven学习(七)Maven工程单一架构案例_第34张图片

package com.sr.maven.service;

import com.sr.maven.entity.Emp;

public interface EmpService {
    Emp getEmpByLoginAccount(String loginAccount, String loginPassword);
}

package com.sr.maven.service.impl;

import com.sr.maven.dao.api.EmpDao;
import com.sr.maven.dao.impl.EmpDaoImpl;
import com.sr.maven.entity.Emp;
import com.sr.maven.exception.LoginFailException;
import com.sr.maven.service.EmpService;
import com.sr.maven.util.ImperialCourtConst;
import com.sr.maven.util.MD5Util;

public class EmpServiceImpl implements EmpService {

    private EmpDao empDao = new EmpDaoImpl();

    @Override
    public Emp getEmpByLoginAccount(String loginAccount, String loginPassword) {

        //1.对密码进行加密
        String encodeLoginPassword = MD5Util.encode(loginPassword);

        //2.根据账户和密码加密密码查询数据库
        Emp emp = empDao.selectEmpByLoginAccount(loginAccount,loginPassword);

        //3.检查Emp对象是否为空
        if(emp !=null ){

            // ①不为null,返回emp
            return emp;
        }else
        {
            //抛出登录异常失败
            throw new LoginFailException(ImperialCourtConst.LOGIN_FAIL_MESSAGE);
        }
    }
}

④创建登录失败异常

Maven学习(七)Maven工程单一架构案例_第35张图片

package com.sr.maven.exception;

public class LoginFailException extends RuntimeException{

    public LoginFailException() {
        super();
    }

    public LoginFailException(String message) {
        super(message);
    }

    public LoginFailException(String message, Throwable cause) {
        super(message, cause);
    }

    public LoginFailException(Throwable cause) {
        super(cause);
    }

    protected LoginFailException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

⑤增加一个常量

Maven学习(七)Maven工程单一架构案例_第36张图片

⑥创建AuthServlet类

Maven学习(七)Maven工程单一架构案例_第37张图片

package com.sr.maven.servlet.module;

import com.sr.maven.entity.Emp;
import com.sr.maven.exception.LoginFailException;
import com.sr.maven.service.EmpService;
import com.sr.maven.service.impl.EmpServiceImpl;
import com.sr.maven.servlet.base.ModelBaseServlet;
import com.sr.maven.util.ImperialCourtConst;

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

public class AuthServlet  extends ModelBaseServlet {

    private EmpService empService = new EmpServiceImpl();

    protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        try {
            //1.先获取请求参数
            String loginAccount = req.getParameter("loginAccount");
            String loginPassword = req.getParameter("loginPassword");
            //2.调用EmpService 的方法,执行登录的逻辑
            Emp emp =  empService.getEmpByLoginAccount(loginAccount,loginPassword);
            //3. 通过requet获取HTTPSession
            HttpSession session = req.getSession();
            //4.将查询的Emp对象存入Session域
            session.setAttribute(ImperialCourtConst.LOGIN_EMP_ATTR_NAME,emp);
            //5.前往指定的页面视图
            String templateName  = "temp";
            processTemplate(templateName,req,resp);
        }catch (Exception e){
            e.printStackTrace();
            //判断此处是否是 登录失败异常
            if(e instanceof LoginFailException){

            //如果是登录失败异常跳转回登录页面
            //存入请求域
                req.setAttribute("message",e.getMessage());
            //处理视图:index
            processTemplate("index",req,resp);

            }else{
            //如果不是登录异常则封装为运行时异常继续抛出
                throw  new RuntimeException(e);
            }

        }

    }
}

⑦temp页面

Maven学习(七)Maven工程单一架构案例_第38张图片

DOCTYPE html>
<html lang="en" xml:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>temptitle>
head>
<body>
  <p th:text="${session.loginInfo}">p>
body>
html>

⑧注册,在web.xml中增加信息

 <servlet>
        <servlet-name>authServletservlet-name>
        <servlet-class>com.sr.maven.servlet.module.AuthServletservlet-class>
    servlet>

    <servlet-mapping>
        <servlet-name>authServletservlet-name>
        <url-pattern>/authurl-pattern>
    servlet-mapping>

⑨运行结果

帐号密码: xiaoxuanzi1654 16540504
Maven学习(七)Maven工程单一架构案例_第39张图片

3.退出登录

①在临时页面编写超链接

Maven学习(七)Maven工程单一架构案例_第40张图片
当前完整代码

DOCTYPE html>
<html lang="en" xml:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>temptitle>
head>
<body>
  <p th:text="${session.loginInfo}">p>
  <a th:href="@{/auth?method=logout}">退朝a>
body>
html>

②在AuthServlet编写退出的逻辑

    protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.通过request 对象获取 HttpSession对象
        HttpSession session = req.getSession();

        //2.将HttpSession设置失效
        session.invalidate();

        //3.回到index页面
        processTemplate("index",req,resp);
    }
}

七、业务功能:显示列表

1.流程图

Maven学习(七)Maven工程单一架构案例_第41张图片

2.创建组件

①创建Java类

Maven学习(七)Maven工程单一架构案例_第42张图片

package com.sr.maven.servlet.module;

import com.sr.maven.entity.Memorials;
import com.sr.maven.service.MemorialsService;
import com.sr.maven.service.impl.MemorialsServiceImpl;
import com.sr.maven.servlet.base.ModelBaseServlet;

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

public class WorkServlet extends ModelBaseServlet {

    private MemorialsService memorialsService = new MemorialsServiceImpl();

    protected void showMemorialsDigestList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //. 1.调用Service方法查询数据
        List<Memorials> list = memorialsService.getAllMemorialsDigest();

        //将查询到的数据存入请求域
        String templateName = "memorials-list";

        processTemplate(templateName,req,resp);


    }
}

package com.sr.maven.service;

import com.sr.maven.entity.Memorials;

import java.util.List;

public interface MemorialsService {
    List<Memorials> getAllMemorialsDigest();
}

package com.sr.maven.service.impl;

import com.sr.maven.dao.api.MemorialsDao;
import com.sr.maven.dao.impl.MemorialsDaoImpl;
import com.sr.maven.entity.Memorials;
import com.sr.maven.service.MemorialsService;

import java.util.List;

public class MemorialsServiceImpl implements MemorialsService {

    private MemorialsDao memorialsDao = new MemorialsDaoImpl();


    @Override
    public List<Memorials> getAllMemorialsDigest() {

      return memorialsDao.selectAllMemorialsDigest();
    }
}

package com.sr.maven.dao.api;

import com.sr.maven.entity.Memorials;

import java.util.List;

public interface MemorialsDao {
    List<Memorials> selectAllMemorialsDigest();
}

package com.sr.maven.dao.impl;

import com.sr.maven.dao.BaseDao;
import com.sr.maven.dao.api.MemorialsDao;
import com.sr.maven.entity.Memorials;

import java.util.List;

public class MemorialsDaoImpl extends BaseDao<Memorials> implements MemorialsDao {
    @Override
    public List<Memorials> selectAllMemorialsDigest() {

        String sql = "SELECT\n" +
                "\tmemorials_id memorialsId,\n" +
                "\tmemorials_title memorialsTitle,\n" +
                "\tconcat(left(memorials_content,10),'...') as memorialsContentDigest,\n" +
                "\tmemorials_content as memorialsContent,\n" +
                "\tmemorials_emp as memorialsEmp,\n" +
                "\temp_name  as memorialsEmpEmpName,\n" +
                "\tmemorials_create_time as memorialsCreateTime,\n" +
                "\tfeedback_time as feedbackTime,\n" +
                "\tfeedback_content as feedbackContent,\n" +
                "\tmemorials_status  as memorialsStatus\n" +
                "FROM\n" +
                "\tt_memorials m\n" +
                "\tleft join t_emp e on m.memorials_emp=e.emp_id";
        return   super.getBeanList(sql,Memorials.class);
    }
}

② 注册,在web.xml中增加信息


    <servlet>
        <servlet-name>workServletservlet-name>
        <servlet-class>com.sr.maven.servlet.module.WorkServletservlet-class>
    servlet>

    <servlet-mapping>
        <servlet-name>workServletservlet-name>
        <url-pattern>/workurl-pattern>
    servlet-mapping>

3.页面显示

Maven学习(七)Maven工程单一架构案例_第43张图片

DOCTYPE html>
<html lang="en" xml:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>temptitle>
    <style type="text/css">
        table{
            border-collapse: collapse;
            margin: 0px auto 0px auto;
        }
        table th ,td{
            border: 1px solid black;
            text-align: center;
        }
        div{
            text-align: right;
        }

    style>
head>
<body>
    
    <div>
        <span th:if="${session.loginInfo.empPosition == 'emperor'}">恭请皇上圣安span>
        <span th:if="${session.loginInfo.empPosition == 'minister'}"><span th:text="${session.loginInfo.empName}">span>大人请安span>
        <a th:href="@{/auth?method=logout}">退朝a>
    div>
    
    <table>
        <thead>
            <th>奏折标题th>
            <th>内容摘要th>
            <th>上疏大臣th>
            <th>上疏时间th>
            <th>奏折状态th>
            <th>奏折详情th>
        thead>
        <tbody th:if="${#lists.isEmpty(memorialsList)}">
            <tr>
                <td colspan="6">没有人上过折子td>
            tr>
        tbody>
        <tbody th:if="${not #lists.isEmpty(memorialsList)}">
        <tr th:each="memorials : ${memorialsList}">
            <td th:switch="${memorials.memorialsStatus}">
                <span th:text="${memorials.memorialsTitle}" th:case="0" style="color: red">奏折标题span>
                <span th:text="${memorials.memorialsTitle}"  th:case="1" style="color: blue">奏折标题span>
                <span th:text="${memorials.memorialsTitle}"  th:case="2" >奏折标题span>
            td>
            <td th:switch="${memorials.memorialsStatus}">
                <span th:text="${memorials.memorialsContentDigest}" th:case="0" style="color: red">内容摘要span>
                <span th:text="${memorials.memorialsContentDigest}"  th:case="1" style="color: blue">内容摘要span>
                <span th:text="${memorials.memorialsContentDigest}"  th:case="2" >内容摘要span>
            td>

            <td th:switch="${memorials.memorialsStatus}">
                <span th:text="${memorials.memorialsEmpEmpName}" th:case="0" style="color: red">上疏大臣span>
                <span th:text="${memorials.memorialsEmpEmpName}"  th:case="1" style="color: blue">上疏大臣span>
                <span th:text="${memorials.memorialsEmpEmpName}"  th:case="2" >上疏大臣span>
            td>

            <td th:switch="${memorials.memorialsStatus}">
                <span th:text="${memorials.memorialsCreateTime}" th:case="0" style="color: red">上疏时间span>
                <span th:text="${memorials.memorialsCreateTime}"  th:case="1" style="color: blue">上疏时间span>
                <span th:text="${memorials.memorialsCreateTime}"  th:case="2" >上疏时间span>
            td>


            <td th:switch="${memorials.memorialsStatus}">
                <span  th:case="0" style="color: red">未读span>
                <span  th:case="1" style="color: blue">已读span>
                <span  th:case="2" >已批示span>
            td>

            <td>
                <a th:href="@{/work?(method='memorialsDetail',memorialsId=${memorials.memorialsId})}">奏折详情a>
            td>
        tr>
        tbody>
    table>
body>
html>

4.和登录对接

将authServlet中登录跳转temp的代码替换为刚才做的列表页
Maven学习(七)Maven工程单一架构案例_第44张图片

      resp.sendRedirect(req.getContextPath()+"/work?method=showMemorialsDigestList");

八、业务功能:显示详情

1.详情页代码

Maven学习(七)Maven工程单一架构案例_第45张图片

DOCTYPE html>
<html lang="en" xml:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>temptitle>
    <style type="text/css">
        table {
            border-collapse: collapse;
            margin: 0px auto 0px auto;
        }

        table th, td {
            border: 1px solid black;
            text-align: center;
        }

        div {
            text-align: center;
        }

    style>
head>
<body>

<div>
    <span th:if="${session.loginInfo.empPosition == 'emperor'}">恭请皇上圣安span>
    <span th:if="${session.loginInfo.empPosition == 'minister'}"><span th:text="${session.loginInfo.empName}">span>大人请安span>
    <a th:href="@{/auth?method=logout}">退朝a>
div>

<table>
    <tr>
        <td>奏折标题td>
        <td th:text="${memorials.memorialsTitle}">td>
    tr>
    <tr>
        <td>上疏大臣td>
        <td th:text="${memorials.memorialsEmpEmpName}">td>
    tr>
    <tr>
        <td>上疏时间td>
        <td th:text="${memorials.memorialsCreateTime}">td>
    tr>
    <tr>
        <td>奏折内容td>
        <td th:text="${memorials.memorialsContent}">td>
    tr>
    <tr th:if="${memorials.memorialsStatus == 2}">
        <td>批复时间td>
        <td th:text="${memorials.feedbackTime}">td>
    tr>
    <tr  th:if="${memorials.memorialsStatus == 2}">
        <td>批复内容td>
        <td th:text="${memorials.feedbackContent}">td>
    tr>
table>

<div th:if="${memorials.memorialsStatus != 2}">
 <form th:action="@{/work}" method="post">
        <input type="hidden" name="method" value="feedback">
        <input type="hidden" name="memorialsId" th:value="${memorials.memorialsId}">
        <textarea name="feedbackContent">

        textarea>
        <button type="submit">御批button>
    form>
div>

<a th:href="@{/work?method=showMemorialsDigestList}">返回列表a>
body>
html>

2.workServlet方法

protected void memorialsDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1。获取请求参数读取 memorialsId
        String memorialsId = req.getParameter("memorialsId");

        //2.根据memorialsId查询 对象

        Memorials memorials = memorialsService.getMemorialsById(memorialsId);

        //更新为 已读
        if (memorials.getMemorialsStatus() == 0) {
            memorialsService.updateMemorialsStatus(memorialsId, 1);
        }
        //3.放入请求域
        req.setAttribute("memorials", memorials);
        //解析渲染页面
        String templateName = "memorials-detail";
        processTemplate(templateName, req, resp);

    }

3.MemorialsService方法

  Memorials getMemorialsById(String memorialsId);

  void updateMemorialsStatus(String memorialsId, int i);

4.MemorialsServiceImpl方法增加

  @Override
    public Memorials getMemorialsById(String memorialsId) {
        return memorialsDao.selectMemorialsById(memorialsId);
    }

    @Override
    public void updateMemorialsStatus(String memorialsId, int i) {
        memorialsDao.updateMemorialsStatus(memorialsId,i);
    }

5.MemorialsDao方法


    Memorials selectMemorialsById(String memorialsId);

    void updateMemorialsStatus(String memorialsId, int i);

5.MemorialsDaoImpl方法

   @Override
    public Memorials selectMemorialsById(String memorialsId) {
        String sql = "SELECT\n" +
                "\tmemorials_id memorialsId,\n" +
                "\tmemorials_title memorialsTitle,\n" +
                "\tconcat(left(memorials_content,10),'...') as memorialsContentDigest,\n" +
                "\tmemorials_content as memorialsContent,\n" +
                "\tmemorials_emp as memorialsEmp,\n" +
                "\temp_name  as memorialsEmpEmpName,\n" +
                "\tmemorials_create_time as memorialsCreateTime,\n" +
                "\tfeedback_time as feedbackTime,\n" +
                "\tfeedback_content as feedbackContent,\n" +
                "\tmemorials_status  as memorialsStatus\n" +
                "FROM\n" +
                "\tt_memorials m\n" +
                "\tleft join t_emp e on m.memorials_emp=e.emp_id where m.memorials_id = ?";
        return super.getSingleBean(sql,Memorials.class,memorialsId);
    }

    @Override
    public void updateMemorialsStatus(String memorialsId, int i) {
        String sql = "update t_memorials set memorials_status = ? where memorials_id = ?";
        super.update(sql,i,memorialsId);
    }

6. 结果图展示

Maven学习(七)Maven工程单一架构案例_第46张图片

九、业务功能:回复

1.WorkServlet方法

    protected void feedback(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.获取回复的内容参数
        String content = req.getParameter("feedbackContent");
        String memorialsId = req.getParameter("memorialsId");

        //更新内容
        memorialsService.updateFeedback(memorialsId,content);

        //重定向到列表页
        resp.sendRedirect(req.getContextPath()+"/work?method=showMemorialsDigestList");
    }

2.MemorialsService方法

  void updateFeedback(String memorialsId, String content);

3.MemorialsServiceImpl方法

  @Override
    public void updateFeedback(String memorialsId, String content) {
        memorialsDao.updateFeedback(memorialsId,content);
    }

4.MemorialsDao方法

void updateFeedback(String memorialsId, String content);

5.MemorialsDaoImpl方法


    @Override
    public void updateFeedback(String memorialsId, String content) {
        String sql = "update t_memorials set memorials_status = ? ,feedback_content = ?, feedback_time =? where memorials_id = ?";
        String currentTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        super.update(sql,2,content,currentTime,memorialsId);
    }

十、业务功能:登录检查

1.逻辑

Maven学习(七)Maven工程单一架构案例_第47张图片

2.创建LoginFilter

Maven学习(七)Maven工程单一架构案例_第48张图片

package com.sr.maven.filter;

import com.sr.maven.util.ImperialCourtConst;

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

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //1.获取HttpSession
        HttpServletRequest request = (HttpServletRequest)servletRequest;

        HttpSession session = request.getSession();

        //尝试从Session域获取已登录的对象
        Object loginEmp = session.getAttribute(ImperialCourtConst.LOGIN_EMP_ATTR_NAME);

        //判断loginEmp是否为空
        if(loginEmp != null){
            filterChain.doFilter(request,servletResponse);
            return;
        }

        request.setAttribute("systemMessage",ImperialCourtConst.ACCESS_DENIED_MESSAGE);
        request.getRequestDispatcher("/").forward(request,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

3.配置web.xml

把LoginFilter放在txFilter前面,一个过滤链的操作,代表前后顺序,节省性能


    <filter>
        <filter-name>loginFilterfilter-name>
        <filter-class>com.sr.maven.filter.LoginFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>loginFilterfilter-name>
        <url-pattern>/workurl-pattern>
    filter-mapping>

Maven学习(七)Maven工程单一架构案例_第49张图片

十一、打包部署

1.适配环境信息

记得修改对应的配置文件信息,比如数据库地址等,跟环境有关的信息

2.跳过测试打包

mvn clean package -Dmaven.test.skip=true

Maven学习(七)Maven工程单一架构案例_第50张图片

3.上传war包

自己选择上传到Linux或者Windows等,Tomcat对应的webapp包内

4.启动Tomcat

Linux

tomcat目录/bin/startup.sh

Windows
tomcat目录/bin/startup.bat双击

5.访问测试

自行浏览器地址测试
在这里插入图片描述

你可能感兴趣的:(Maven,maven,学习)