Spring MVC 02 单例模式及统一异常处理

13 篇文章 0 订阅
10 篇文章 0 订阅

单例模式及统一异常处理

一、学习目标与任务

1.1回顾提问:

1.MVC设计模式是什么?

2.Spring MVC的架构是什么?

3.Spring MVC的请求处理流程是什么?

4.Spring MVC框架是基于哪个核心的Servlet?

5.Spring MVC如何实现View与Controller之间的参数传递?

1.2学习目标
  1. 掌握并理解单例模式
  2. 搭建SSM框架
  3. 掌握Spring MVC访问静态文件
  4. 掌握Servlet API作为控制器接口入参
  5. 掌握Spring MVC异常(局部、全局)处理
1.3学习任务
  1. 改造读取数据库配置文件的工具类为单例模式
  2. 改造724系统-登录、注销、查询用户列表功能
  3. 使用Spring MVC(局部)异常处理,提示登录失败的原因
  4. 使用Spring MVC(全局)异常处理,提示登录失败的原因
  5. 改造724系统-供货商列表查询功能

二、单例模式

1.1.问题分析
  • 回顾学习JDBC操作数据库的基类(BaseDao.java)

在这里插入图片描述

  • database.properties文件
driver=com.mysql.cj.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,字符集设置为utf-8,并根据需要设置时区
url=jdbc:mysql://127.0.0.1:3306/cvs_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
user=root
password=root
  • ConfigManager工具类:
package cn.cvs.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

//存在问题:每个线程操作数据库都需new一个BaseDao实例,即每个线程都会单独加载配置文件,影响系统性能
public class ConfigManager {
	private static Properties properties;
	static{
   init();
 } 
	public static void init(){
		String configFile = "database.properties";
		properties = new Properties();
		InputStream is = 
		ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
		try {
			properties.load(is);
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static String getProperty(String key){
		return properties.getProperty(key);
	}
}
  • BaseDao工具类:
package cn.cvs.dao;

import cn.cvs.utils.ConfigManager;

import java.sql.*;

/**
 * 操作数据库的基类--静态类
 * @author Aiden
*
*/
public class BaseDao {

	/**
	 * 获取数据库连接对象
	 * @return
	 */
	public static Connection getConnection(){
		Connection connection = null;
		String driver = ConfigManager.getProperty("driver"); 
     String url = ConfigManager.getProperty("url");
     String user = ConfigManager.getProperty("user");
     String password = ConfigManager.getProperty("password");
		try {
			Class.forName(driver);
			connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return connection;
	}
	/**
	 * 查询操作
	 */
	public static ResultSet execute(Connection connection,PreparedStatement pstm,ResultSet rs,
			String sql,Object[] params) throws Exception{
		pstm = connection.prepareStatement(sql);
		for(int i = 0; i < params.length; i++){
			pstm.setObject(i+1, params[i]);
		}
		rs = pstm.executeQuery();
		return rs;
	}
	/**
	 * 更新操作
	 */
	public static int execute(Connection connection,PreparedStatement pstm,
			String sql,Object[] params) throws Exception{
		int updateRows = 0;
		pstm = connection.prepareStatement(sql);
		for(int i = 0; i < params.length; i++){
			pstm.setObject(i+1, params[i]);
		}
		updateRows = pstm.executeUpdate();
		return updateRows;
	}
	
	/**
	 * 释放资源
	 */
	public static boolean closeResource(Connection connection,PreparedStatement pstm,ResultSet rs){
		boolean flag = true;
		if(rs != null){
			try {
				rs.close();
				rs = null;//GC回收
			} catch (SQLException e) {
				e.printStackTrace();
				flag = false;
			}
		}
		if(pstm != null){
			try {
				pstm.close();
				pstm = null;//GC回收
			} catch (SQLException e) {
				e.printStackTrace();
				flag = false;
			}
		}
		if(connection != null){
			try {
				connection.close();
				connection = null;//GC回收
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				flag = false;
			}
		}
		
		return flag;
	}

}

问题1:

  • BaseDao:操作数据库的基类
    • init()方法
      • 从配置文件中读取数据库连接的初始化参数
      • 读取配置文件属于I/O操作,十分消耗资源,影响系统性能
  • 每个线程操作数据库都需new一个BaseDao实例,即每个线程都会单独加载配置文件,影响系统性能,该如何解决呢?

分析:

  • 对于每个线程,可共享一个实例
  • 单例模式

1.2单例模式的概念

单例模式:系统运行期间,有且仅有一个实例

  • 一个类只有一个实例

    • 私有构造方法
  • 自行创建实例对象

    • 定义了静态的该类私有对象
  • 对外提供实例对象

    • 提供一个静态的公有方法,返回创建的或者获取本身的静态私有对象

1.3单例模式实现的方式
1.3.1简单的单例模式实现
package cn.cvs.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

//通过单例模式读取配置文件
public class ConfigManager {
   //1.定义静态实例属性
	private static ConfigManager configManager;
	private static Properties properties;
   
	//2.私有构造器-读取数据库配置文件
	private ConfigManager(){
		String configFile = "database.properties";
		properties = new Properties();
		InputStream is =
   ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
		try {
		properties.load(is);
		is.close();
		 } catch (IOException e) {
			  e.printStackTrace();
		 }
	}

	//3.对外提供的获取ConfigManager实例的方法
	public static ConfigManager getInstance(){
		if(configManager == null){
		configManager = new ConfigManager();
		}
		return configManager;
	}

	public String getValue(String key){
		return properties.getProperty(key);
	}
}

问题2:

  • 在并发环境下,上述的单例模式实现是否存在弊端,线程是否安全?是否会出现多个configManager实例?

分析:

  1. 懒汉模式
  2. 饿汉模式

1.3.2懒汉模式-synchronized

懒汉模式:

  • 类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例

  • 特点

  • 线程不安全

  • 延迟加载(Lazy Loading)

  • 如何解决线程安全问题?

  • synchronized关键字

  • 在方法中添加 synchronized 关键字:public static synchronized ConfigManager getInstance()

package cn.cvs.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

//通过单例模式读取配置文件
public class ConfigManager {
	private static ConfigManager configManager;
	private static Properties properties;
	//私有构造器-读取数据库配置文件
	private ConfigManager(){
		String configFile = "database.properties";
		properties = new Properties();
		InputStream is =
				ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
		try {
			properties.load(is);
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	// 对外提供的获取ConfigManager实例的方法
	public static synchronized ConfigManager getInstance(){
		if(configManager == null){
			configManager = new ConfigManager();
		}
		return configManager;
	}

	public String getValue(String key){
		return properties.getProperty(key);
	}
}

1.3.3饿汉模式
  • 类加载的时候,就完成初始化
  • 特点
  • 线程安全
  • 不具备延迟加载特性

饿汉模式示例

  1. 直接创建实例对象:
  • private static ConfigManager configManager = new ConfigManager();
  1. 定义获取实例对象的方法getInstance:
  • public static ConfigManager getInstance()
package cn.cvs.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

//通过单例模式读取配置文件
public class ConfigManager {

	private static ConfigManager configManager = new ConfigManager();
	private static Properties properties;
	
//私有构造器-读取数据库配置文件
	private ConfigManager(){
		String configFile = "database.properties";
		properties = new Properties();
		InputStream is =
				ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
		try {
			properties.load(is);
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/*//全局访问点-(懒汉模式)
	public static synchronized ConfigManager getInstance(){
		if(configManager == null){
			configManager = new ConfigManager();
		}
		return configManager;
	}*/

	//饿汉模式
	public static ConfigManager getInstance(){
		return configManager;
	}

	public String getValue(String key){
		return properties.getProperty(key);
	}
}

问题3:

  • 若实例化单例类(比如说:ConfigManager)很消耗资源,我们希望它可以延迟加载,即不想让它在类加载的时候就实例化,应该如何处理呢?

分析:

  • 要求饿汉模式同时要具备延迟加载的特性

  • 静态内部类

1.3.4饿汉模式-静态内部类
  1. 定义Single类,在类的内部增加内部静态类 SingleHelper
package cn.cvs.utils;

public class Single {
	
	private static Single single;
	
//私有化构造
	private Single(){
	   // 整个运行期间,只执行一次的业务代码操作,如:读取配置文件的操作。
//......
	}
	
	public static class SingleHelper{
		private static final Single INSTANCE = new Single();
	}
	//对外提供获取本实例的方法
	public static Single getInstance(){
		single = SingleHelper.INSTANCE;
		return single;
	}
	public static Single test(){
		return single;
	}
	
}
  1. 测试分别使用Single.test(); 与Single.getInstance();获取对象
package cn.cvs.utils;

public class TestSingle {
	public static void main(String[] args) {
		Single single = Single.test();
		System.out.println("调用Singleton.test()方法获取实例对象:" + single);

		single = Single.getInstance();
		System.out.println("第一次调用Singleton.getInstance()方法获取实例对象:" + single);

		single = Single.getInstance();
		System.out.println("第二次调用Singleton.getInstance()方法获取实例对象:" + single);
	}
}
  1. 运行结果:

在这里插入图片描述


学员操作—增加读取数据库配置文件的工具类

需求说明:

  1. 在上章学员操作的基础上增加ConfigManager.java的工具类完成数据库配置文件的读取
  2. 该类设计为单例模式,使用懒汉模式、饿汉模式、静态内部类等方式均可,但需要考虑线程安全问题

1.4.Spring MVC中的单例模式
  • Spring MVC-Controller

    • 默认scope为singleton
    • 速度和性能优越
  • 在Spring MVC的Controller中声明成员变量,需要注意线程安全问题

  • 一般情况下,Controller内的成员变量就只有service对象

package cn.cvs.controller;
import cn.cvs.pojo.SysUser;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

@Controller
@RequestMapping("/user")
@Scope("prototype")//默认scope为singleton
public class SysUserController {
	private Logger logger = Logger.getLogger(SysUserController.class);

	private ArrayList<SysUser> userList = new ArrayList<SysUser>();
	// 用于返回查询到的用户数据
	private ArrayList<SysUser> queryUserList = new ArrayList<SysUser>();
	
 public SysUserController(){
			userList.add(new SysUser(5,"zhaojing","赵静","5555555",1
					, "13054784445","上海市宝山区",1,1,new Date(),1, new Date()));
			userList.add(new SysUser(4,"wanglin","王林","4444444",1
					,"18965652364","北京市学院路",1,1,new Date(),1,new Date()));
			userList.add(new SysUser(1,"test001","测试用户001","1111111",1
					, "13566669998","北京市朝阳区",1,1,new Date(),1, new Date()));
			userList.add(new SysUser(2,"zhaoyan","赵燕","2222222",1
					, "18678786545","北京市海淀区",1,1,new Date(),1, new Date()));
			userList.add(new SysUser(3,"test003","测试用户003","1111111",1
					,"13121334531","北京市海淀区",1,1,new Date(),1,new Date()));
	}

	/**
	 * 查询用户列表
	 * @param model
	 * @return
	 */
	@GetMapping("/list")
	public String list(Model model){
		logger.info("当查询条件位空时,查询用户信息" + this);
		queryUserList.clear();
		queryUserList.addAll(userList);
		model.addAttribute("queryUserList",userList);
		return "sysUser/sysUserList";
	}

	/**
	 * 根据用户名称查询用户列表
	 * @param realName
	 * @param model
	 * @return
	 */
	@PostMapping("/list")
	public String list(@RequestParam(value="realName",required=false) String realName, Model model){
		logger.info("查询条件:【realName】= " + realName +", 查询用户信息");
		queryUserList.clear();
		if(realName != null && !realName.equals("")){
			for(SysUser user:userList){
				if(user.getRealName().indexOf(realName) != -1){
					queryUserList.add(user);
				}
			}
		}else{
			queryUserList.addAll(userList);
		}
		model.addAttribute("queryUserList",queryUserList);
		return "sysUser/sysUserList";
	}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
      pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>查询用户信息</title>
</head>
<body>
<h1>查询用户列表</h1>
<form action="${pageContext.request.contextPath }/user/list" method="post">
 用户名称:<input type="text" name="realName" value=""/>
 <input type="submit" name="查询"/>
</form>

<c:forEach var="sysUser" items="${queryUserList }">
 <div>
     id= ${sysUser.id };
     用户编码= ${sysUser.account };
     用户名称= ${sysUser.realName };
     用户密码= ${sysUser.password };
     用户地址= ${sysUser.address };
 </div>
</c:forEach>
</body>
</html>
  • 注意当控制器获取视图传递的值出现乱码时需要配置过滤器
<!-- 配置编码方式过滤器,注意一点:要配置在所有过滤器的前面 -->
<filter>
     <filter-name>CharacterEncodingFilter</filter-name>
     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
     <init-param>
         <param-name>encoding</param-name>
         <param-value>utf-8</param-value>
     </init-param>
 </filter>
 <filter-mapping>
     <filter-name>CharacterEncodingFilter</filter-name>
     <url-pattern>/*</url-pattern>
</filter-mapping>

三、搭建项目运行环境

3.1.实现步骤
  • 添加框架整合所依赖的jar包

    • Spring、Spring MVC框架对应的jar包
  • 拆分配置文件

    • 创建Spring配置文件,用来处理Service层和Dao层的相关功能
  • 配置web.xml文件

    • ContextLoaderListener监听器
      • 在Web容器启动的时候初始化Spring容器
    • contextConfigLocation参数
      • 加载指定的配置文件

3.2.改造登录、注销功能

实现步骤:

  1. 使用@Repository或@Component标注DAO组件
  2. 使用@Service或@Component标注Service组件
    • 使用@Autowired或@Resource为Service注入DAO组件
  3. 改造Controller层
    • 使用@Autowired或@Resource为Controller注入Service组件
    • 创建SysUserController,实现以下业务功能:
      1. 跳转到登录页面
      2. 登录
      3. 跳转到首页
  4. 改造View层
    • 静态资源文件 (js、css、images等)
    • 用户登录页面(login.jsp)和首页(index.jsp)
    • 公共页面(foot.jsp、head.jsp)

3.3.改造CVS-用户登录功能
3.3.1 web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">

    <display-name>Aiden Create Spring Web MVC</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-*.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

3.3.2 applicationContext-jdbc.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 使spring扫描包下的所有类,让标注spring注解的类生效-->
    <!-- 若扫描到有 @Repository、@Service、@Component @Controller 等这些注解的类,则把这些类注册为bean-->
    <context:component-scan base-package="com.aiden.springmvc.cvs.dao"></context:component-scan>
    <context:component-scan base-package="com.aiden.springmvc.cvs.service"></context:component-scan>
</beans>
3.3.3 springmvc-servlet配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 1.开启注解扫描-->
    <mvc:annotation-driven/>
    <!-- 2.使spring扫描controller包下的所有类,让标注@controller注解的类生效 -->
    <context:component-scan base-package="com.aiden.springmvc.cvs.controller"/>
    <!-- 3.静态资源映射,可以配置多个 -->
    <mvc:resources mapping="/statics/**" location="/statics/"/>
    <!-- 完成视图的对应 -->
    <!-- 4.对转向页面的路径解析。prefix:前缀, suffix:后缀 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
3.3.4 database.properties文件
driver=com.mysql.cj.jdbc.Driver
#在和mysql传递数据的过程中,使用unicode编码格式,字符集设置为utf-8,并根据需要设置时区
url=jdbc:mysql://127.0.0.1:3306/cvs_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
user=root
password=root
3.3.5 log4j.properties文件
log4j.rootLogger=debug,CONSOLE,file

log4j.logger.cn.cvs=debug
log4j.logger.org.apache.ibatis=debug
log4j.logger.org.mybatis.spring=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug


log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=debug
log4j.appender.CONSOLE.DatePattern=yyyy-MM-dd
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n


log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern=yyyy-MM-dd
log4j.appender.file.File=${springmvc-02.root}/logs/log.log
log4j.appender.file.Append=true
log4j.appender.file.Threshold=debug
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n


log4j.logger.com.opensymphony.xwork2=debug

3.3.6 SysUserDao
package com.aiden.springmvc.cvs.dao;

import com.aiden.springmvc.cvs.pojo.SysUser;

import java.sql.Connection;
import java.util.List;

/**
 * DAO接口
  *
 * @author Aiden
  */
public interface SysUserDao {
        /**
     * 增加用户信息
         *
     * @param connection
     * @param sysUser    用户对象
     * @return
     * @throws Exception
         */
        int insert(Connection connection, SysUser sysUser) throws Exception;

        /**
     * 通过用户编码获取User
         *
     * @param connection
     * @param account
     * @return
     * @throws Exception
         */
        SysUser findUserByAccount(Connection connection, String account) throws Exception;

        /**
     * 通过条件查询-userList
         *
     * @param connection
     * @param realName   用户名称
     * @param userRoleId 角色编号
     * @return
     * @throws Exception
         */
        List<SysUser> findList(Connection connection, String realName, int userRoleId, int currentPageNo, int pageSize) throws Exception;

        /**
     * 通过条件查询-用户表记录数
         *
     * @param connection
     * @param realName   用户名称
     * @param userRoleId 角色编号
     * @return
     * @throws Exception
         */
        int getTotalCount(Connection connection, String realName, int userRoleId) throws Exception;

        /**
     * 通过用户编号删除user
         *
     * @param id
     * @return
     * @throws Exception
         */
        int deleteUserById(Connection connection, Integer id) throws Exception;


        /**
     * 通过userId获取user
         *
     * @param connection
     * @param id         用户编号
     * @return
     * @throws Exception
         */
        SysUser getUserById(Connection connection, String id) throws Exception;

        /**
     * 修改用户信息
         *
     * @param connection
     * @param user       用户对象
     * @return
     * @throws Exception
         */
        int modify(Connection connection, SysUser user) throws Exception;


        /**
     * 修改当前用户密码
         *
     * @param connection
     * @param id         用户编号
     * @param password   用户密码
     * @return
     * @throws Exception
         */
        int updatePwd(Connection connection, int id, String password) throws Exception;
}
3.3.7 ConfigManager
package com.aiden.springmvc.cvs.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @author Aiden
 * 读取配置文件的工具类-单例模式
 * [存在问题]:每个线程操作数据库都需new一个BaseDao实例,
 * 即每个线程都会单独加载配置文件,影响系统性能。
 */
public class ConfigManager {

    private static ConfigManager configManager;
    private static Properties properties;
    //私有构造
    private ConfigManager() {
        String configFile = "database.properties";
        InputStream is = null;
        properties = new Properties();
        try {
            is = ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
            properties.load(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 静态内部类
     */
    public static class ConfigManagerHelper {
        private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
    }

    /**
     * 获取ConfigManager实例的方法
     *
     * @return
     */
    public static ConfigManager getInstance() {
        configManager = ConfigManagerHelper.CONFIG_MANAGER;
        return configManager;
    }

    public static String getProperty(String key) {
        return properties.getProperty(key);
    }
}

3.3.8 BaseDao
package com.aiden.springmvc.cvs.dao;

import com.aiden.springmvc.cvs.utils.ConfigManager;

import java.sql.*;

/**
 * 操作数据库的基类--静态类
 *
 * @author Aiden
 */
public class BaseDao {
    private static BaseDao baseDao = new BaseDao();

    /**
     * 私有化构造方法
     */
    private BaseDao() {
        getConnection();
    }

    /**
     * 获取BaseDao实例对象
     *
     * @return
     */
    public static BaseDao getInstance() {
        return baseDao;
    }

    /**
     * 获取数据库连接对象
     *
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        String driver = ConfigManager.getInstance().getProperty("driver");
        String url = ConfigManager.getInstance().getProperty("url");
        String user = ConfigManager.getInstance().getProperty("user");
        String password = ConfigManager.getInstance().getProperty("password");
        try {
            Class.forName(driver);//加载驱动
            connection = DriverManager.getConnection(url, user, password);//建立连接
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 查询操作
     */
    public static ResultSet execute(Connection connection, PreparedStatement stmt, ResultSet rs,
                                    String sql, Object... params) throws Exception {
        stmt = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            stmt.setObject(i + 1, params[i]);
        }
        rs = stmt.executeQuery();
        return rs;
    }

    /**
     * 更新操作
     */
    public static int execute(Connection connection, PreparedStatement stmt,
                              String sql, Object... params) throws Exception {
        int updateRows = 0;
        stmt = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            stmt.setObject(i + 1, params[i]);
        }
        updateRows = stmt.executeUpdate();
        return updateRows;
    }

    /**
     * 释放资源
     */
    public static boolean closeResource(Connection connection, PreparedStatement stmt, ResultSet rs) {
        boolean flag = true;
        if (rs != null) {
            try {
                rs.close();
                rs = null;//GC回收
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
                stmt = null;//GC回收
            } catch (SQLException e) {
                e.printStackTrace();
                flag = false;
            }
        }
        if (connection != null) {
            try {
                connection.close();
                connection = null;//GC回收
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                flag = false;
            }
        }

        return flag;
    }
}
3.3.9 SysUserDaoImpl
package com.aiden.springmvc.cvs.dao.impl;

import com.aiden.springmvc.cvs.dao.BaseDao;
import com.aiden.springmvc.cvs.dao.SysUserDao;
import com.aiden.springmvc.cvs.pojo.SysUser;
import org.springframework.stereotype.Repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
* dao层抛出异常,让service层去捕获处理
*
* @author Aiden
*/
@Repository
public class SysUserDaoImpl implements SysUserDao {


   @Override
   public int insert(Connection connection, SysUser sysUser) throws Exception {
       PreparedStatement stmt = null;
       int updateRows = 0;
       if (null != connection) {
           String sql = "insert into t_sys_user (account,realName,password," +
                   "roleId,sex,birthday,phone,address,createTime,createUserId) " +
                   "values(?,?,?,?,?,?,?,?,?,?)";
           Object[] params = {sysUser.getAccount(), sysUser.getRealName(), sysUser.getPassword(),
                   sysUser.getRoleId(), sysUser.getSex(), sysUser.getBirthday(),
                   sysUser.getPhone(), sysUser.getAddress(), sysUser.getCreatedTime(), sysUser.getCreatedUserId()};
           updateRows = BaseDao.execute(connection, stmt, sql, params);
           BaseDao.closeResource(null, stmt, null);
       }
       return updateRows;
   }

   @Override
   public SysUser findUserByAccount(Connection connection, String account) throws Exception {
       PreparedStatement pstm = null;
       ResultSet rs = null;
       SysUser user = null;
       if (null != connection) {
           String sql = "select * from t_sys_user where account=?";
           Object[] params = {account};
           rs = BaseDao.execute(connection, pstm, rs, sql, params);
           if (rs.next()) {
               user = new SysUser();
               user.setId(rs.getInt("id"));
               user.setAccount(rs.getString("account"));
               user.setRealName(rs.getString("realName"));
               user.setPassword(rs.getString("password"));
               user.setSex(rs.getInt("sex"));
               user.setBirthday(rs.getDate("birthday"));
               user.setPhone(rs.getString("phone"));
               user.setAddress(rs.getString("address"));
               user.setRoleId(rs.getInt("roleId"));
               user.setCreatedUserId(rs.getInt("createdUserId"));
               user.setCreatedTime(rs.getTimestamp("createdTime"));
               user.setUpdatedUserId(rs.getInt("updatedUserId"));
               user.setUpdatedTime(rs.getTimestamp("updatedTime"));
           }
           BaseDao.closeResource(null, pstm, rs);
       }
       return user;
   }

   @Override
   public List<SysUser> findList(Connection connection, String realName, int userRoleId, int currentPageNo, int pageSize) throws Exception {
       PreparedStatement stmt = null;
       ResultSet rs = null;
       List<SysUser> userList = new ArrayList<SysUser>();
       if (connection != null) {
           StringBuffer sql = new StringBuffer();
           sql.append("select u.*,r.roleName as roleIdName from t_sys_user u,t_sys_role r where u.roleId = r.id");
           List<Object> list = new ArrayList<Object>();

           if (userRoleId > 0) {
               sql.append(" and u.roleId = ?");
               list.add(userRoleId);
           }
           sql.append(" order by createdTime DESC limit ?,?");
           currentPageNo = (currentPageNo - 1) * pageSize;

           list.add(currentPageNo);
           list.add(pageSize);

           Object[] params = list.toArray();
           System.out.println("sql ----> " + sql.toString());
           rs = BaseDao.execute(connection, stmt, rs, sql.toString(), params);
           while (rs.next()) {
               SysUser _user = new SysUser();
               _user.setId(rs.getInt("id"));
               _user.setAccount(rs.getString("account"));
               _user.setRealName(rs.getString("realName"));
               _user.setSex(rs.getInt("sex"));
               _user.setBirthday(rs.getDate("birthday"));
               _user.setPhone(rs.getString("phone"));
               _user.setRoleId(rs.getInt("roleId"));
               _user.setRoleIdName(rs.getString("roleIdName"));
               userList.add(_user);
           }
           BaseDao.closeResource(null, stmt, rs);
       }
       return userList;
   }

   @Override
   public int getTotalCount(Connection connection, String realName, int userRoleId) throws Exception {
       PreparedStatement stmt = null;
       ResultSet rs = null;
       int count = 0;
       if (connection != null) {
           StringBuffer sql = new StringBuffer();
           sql.append("select count(1) as count from t_sys_user u,t_sys_role r where u.roleId = r.id");
           List<Object> list = new ArrayList<Object>();

           if (userRoleId > 0) {
               sql.append(" and u.roleId = ?");
               list.add(userRoleId);
           }
           Object[] params = list.toArray();
           System.out.println("sql ----> " + sql.toString());
           rs = BaseDao.execute(connection, stmt, rs, sql.toString(), params);
           if (rs.next()) {
               count = rs.getInt("count");
           }
           BaseDao.closeResource(null, stmt, rs);
       }
       return count;
   }

   @Override
   public int deleteUserById(Connection connection, Integer id) throws Exception {
       PreparedStatement stmt = null;
       int updateRows = 0;
       if (null != connection) {
           String sql = "delete from t_sys_user where id=?";
           Object[] params = {id};
           updateRows = BaseDao.execute(connection, stmt, sql, params);
           BaseDao.closeResource(null, stmt, null);
       }
       return updateRows;
   }

   @Override
   public SysUser getUserById(Connection connection, String id) throws Exception {
       SysUser user = null;
       PreparedStatement stmt = null;
       ResultSet rs = null;
       if (null != connection) {
           String sql = "select u.*,r.roleName as roleIdName from t_sys_user u,t_sys_role r where u.id=? and u.roleId = r.id";
           Object[] params = {id};
           rs = BaseDao.execute(connection, stmt, rs, sql, params);
           if (rs.next()) {
               user = new SysUser();
               user.setId(rs.getInt("id"));
               user.setAccount(rs.getString("account"));
               user.setRealName(rs.getString("realName"));
               user.setPassword(rs.getString("password"));
               user.setSex(rs.getInt("sex"));
               user.setBirthday(rs.getDate("birthday"));
               user.setPhone(rs.getString("phone"));
               user.setAddress(rs.getString("address"));
               user.setRoleId(rs.getInt("roleId"));
               user.setCreatedUserId(rs.getInt("createUserId"));
               user.setCreatedTime(rs.getTimestamp("createdTime"));
               user.setUpdatedUserId(rs.getInt("updatedUserId"));
               user.setUpdatedTime(rs.getTimestamp("updatedTime"));
               user.setRoleIdName(rs.getString("roleIdName"));
           }
           BaseDao.closeResource(null, stmt, rs);
       }
       return user;
   }

   @Override
   public int modify(Connection connection, SysUser user) throws Exception {
       int updateRows = 0;
       PreparedStatement pstm = null;
       if (null != connection) {
           String sql = "update t_sys_user set realName=?,sex=?,birthday=?,phone=?,address=?,roleId=?,updatedUserId=?,updatedTime=? where id = ? ";
           Object[] params = {user.getRealName(), user.getSex(), user.getBirthday(),
                   user.getPhone(), user.getAddress(), user.getRoleId(), user.getUpdatedUserId(),
                   user.getUpdatedTime(), user.getId()};
           updateRows = BaseDao.execute(connection, pstm, sql, params);
           BaseDao.closeResource(null, pstm, null);
       }
       return updateRows;
   }

   @Override
   public int updatePwd(Connection connection, int id, String password) throws Exception {
       int updateRows = 0;
       PreparedStatement stmt = null;
       if (connection != null) {
           String sql = "update t_sys_user set password= ? where id = ?";
           Object[] params = {password, id};
           updateRows = BaseDao.execute(connection, stmt, sql, params);
           BaseDao.closeResource(null, stmt, null);
       }
       return updateRows;
   }
}

3.3.10 SysUserService
package com.aiden.springmvc.cvs.service;

import com.aiden.springmvc.cvs.pojo.SysUser;

import java.util.List;

/**
* 业务接口
*
* @author Aiden
*/
public interface SysUserService {
   /**
    * 增加用户信息
    *
    * @param user
    * @return
    */
   boolean addUser(SysUser user);

   /**
    * 用户登录
    *
    * @param account  用户编码
    * @param password 用户密码
    * @return
    */
   SysUser login(String account, String password);

   /**
    * 根据条件查询用户列表
    *
    * @param queryUserName   用户姓名
    * @param queryUserRoleId 角色编号
    * @return
    */
   List<SysUser> findUserList(String queryUserName, int queryUserRoleId, int currentPageNo, int pageSize);

   /**
    * 根据条件查询用户表记录数
    *
    * @param queryUserName   用户姓名
    * @param queryUserRoleId 角色编号
    * @return
    */
   int getUserCount(String queryUserName, int queryUserRoleId);

   /**
    * 根据用户编码查询用户是存在
    *
    * @param account
    * @return
    */
   SysUser findUserByAccount(String account);

   /**
    * 根据ID删除user
    *
    * @param delId 要删除的用户编号
    * @return
    */
   boolean deleteUserById(Integer delId);

   /**
    * 根据ID查找user
    *
    * @param id
    * @return
    */
   SysUser findUserById(String id);

   /**
    * 修改用户信息
    *
    * @param user
    * @return
    */
   boolean modifyUser(SysUser user);

   /**
    * 根据userId修改密码
    *
    * @param id       用户编号
    * @param password 要修改的密码
    * @return
    */
   boolean updatePwd(int id, String password);
}

3.3.11 SysUserServiceImpl
package com.aiden.springmvc.cvs.service.impl;

import com.aiden.springmvc.cvs.dao.BaseDao;
import com.aiden.springmvc.cvs.dao.SysUserDao;
import com.aiden.springmvc.cvs.pojo.SysUser;
import com.aiden.springmvc.cvs.service.SysUserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
* service业务层捕获异常,进行事务处理
* 事务处理:调用不同dao的多个方法,必须使用同一个connection(connection作为参数传递)
* 事务完成之后,需要在service层进行connection的关闭,在dao层关闭(PreparedStatement和ResultSet对象)
*
* @author Aiden
*/
@Service
public class SysUserServiceImpl implements SysUserService {

   @Resource
   private SysUserDao userDao;

   @Override
   public boolean addUser(SysUser user) {
       boolean flag = false;
       Connection connection = null;
       try {
           connection = BaseDao.getConnection();
           connection.setAutoCommit(false);//开启JDBC事务管理
           int updateRows = userDao.insert(connection, user);
           connection.commit();//提交事务
           if (updateRows > 0) {
               flag = true;
               System.out.println("新增成功!");
           } else {
               System.out.println("新增失败!");
           }

       } catch (Exception e) {
           e.printStackTrace();
           try {
               System.out.println("rollback 回滚事务");
               connection.rollback();
           } catch (SQLException e1) {
               e1.printStackTrace();
           }
       } finally {
           //在service层进行connection连接的关闭
           BaseDao.closeResource(connection, null, null);
       }
       return flag;
   }

   @Override
   public SysUser login(String account, String password) {
       Connection connection = null;
       SysUser user = null;
       try {
           connection = BaseDao.getConnection();
           user = userDao.findUserByAccount(connection, account);
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       //判断密码是否匹配
       if (null != user) {
           if (!user.getPassword().equals(password)) {
               user = null;
           }
       }

       return user;
   }

   @Override
   public List<SysUser> findUserList(String queryUserName, int queryUserRoleId, int currentPageNo, int pageSize) {
       Connection connection = null;
       List<SysUser> userList = null;
       System.out.println("queryUserName ---- > " + queryUserName);
       System.out.println("queryUserRoleId ---- > " + queryUserRoleId);
       System.out.println("currentPageNo ---- > " + currentPageNo);
       System.out.println("pageSize ---- > " + pageSize);
       try {
           connection = BaseDao.getConnection();
           userList = userDao.findList(connection, queryUserName, queryUserRoleId, currentPageNo, pageSize);
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return userList;
   }

   @Override
   public int getUserCount(String queryUserName, int queryUserRoleId) {
       Connection connection = null;
       int count = 0;
       System.out.println("queryUserName ---- > " + queryUserName);
       System.out.println("queryUserRoleId ---- > " + queryUserRoleId);
       try {
           connection = BaseDao.getConnection();
           count = userDao.getTotalCount(connection, queryUserName, queryUserRoleId);
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return count;
   }

   @Override
   public SysUser findUserByAccount(String account) {
       Connection connection = null;
       SysUser user = null;
       try {
           connection = BaseDao.getConnection();
           user = userDao.findUserByAccount(connection, account);
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return user;
   }

   @Override
   public boolean deleteUserById(Integer delId) {
       Connection connection = null;
       boolean flag = false;
       try {
           connection = BaseDao.getConnection();
           if (userDao.deleteUserById(connection, delId) > 0)
               flag = true;
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return flag;
   }

   @Override
   public SysUser findUserById(String id) {
       SysUser user = null;
       Connection connection = null;
       try {
           connection = BaseDao.getConnection();
           user = userDao.getUserById(connection, id);
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
           user = null;
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return user;
   }

   @Override
   public boolean modifyUser(SysUser user) {
       Connection connection = null;
       boolean flag = false;
       try {
           connection = BaseDao.getConnection();
           if (userDao.modify(connection, user) > 0)
               flag = true;
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return flag;
   }

   @Override
   public boolean updatePwd(int id, String password) {
       boolean flag = false;
       Connection connection = null;
       try {
           connection = BaseDao.getConnection();
           if (userDao.updatePwd(connection, id, password) > 0) {
               flag = true;
           }
       } catch (Exception e) {
           //记录异常日志....
           e.printStackTrace();
       } finally {
           BaseDao.closeResource(connection, null, null);
       }
       return flag;
   }
}

3.3.12 SysUserController
package com.aiden.springmvc.cvs.controller;


import com.aiden.springmvc.cvs.pojo.SysUser;
import com.aiden.springmvc.cvs.service.SysUserService;
import com.aiden.springmvc.cvs.utils.Constants;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

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

@Controller
@RequestMapping("user")
public class SysUserController {
       //日志
       private Logger logger = Logger.getLogger(SysUserController.class);
       //用户业务实例对象
       @Resource
       private SysUserService sysUserService;

       @RequestMapping("/hello")
       public String welcome(String realName) {
            logger.info("欢迎使用Spring MVC, realName:" + realName);
            return "index";
       }

       //跳转到登录页面
       @RequestMapping(value = "/toLogin")
       public String login() {
            logger.debug("跳转到登录页面");
            return "login";
       }

       //处理登录请求的方法
       @RequestMapping(value = "/login", method = RequestMethod.POST)
       public String doLogin(@RequestParam String account, @RequestParam String password, HttpServletRequest request, HttpSession session) {
            logger.debug("登录方法");
            //调用service方法,进行用户匹配
            SysUser sysUser = sysUserService.login(account, password);
            if (null != sysUser) {//登录成功
                //放入session
                session.setAttribute(Constants.USER_SESSION, sysUser);
                //重定向到/user/main.htme接口
                return "redirect:/user/toMain";
            } else {
                //页面跳转(login.jsp)带出提示信息--转发
                request.setAttribute("error", "用户名或密码不正确");
                return "login";
            }
       }

       @RequestMapping(value = "/toMain")
       public String main(HttpSession session) {
            if (session.getAttribute(Constants.USER_SESSION) == null) {
                //重定向到登录页面接口
                return "redirect:/user/toLogin";
            }
            return "frame";
       }

       @RequestMapping(value = "/logout")
       public String logout(HttpSession session) {
            //清除session
            session.removeAttribute(Constants.USER_SESSION);
            return "login";
       }
}
3.3.13 login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head lang="en">
   <meta charset="UTF-8">
   <title>系统登录 - 724便利店管理系统</title>
   <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/statics/css/style.css"/>
</head>
<body class="login_bg">
<section class="loginBox">
   <header class="loginHeader">
       <h1>724便利店管理系统</h1>
   </header>
   <section class="loginCont">
       <form class="loginForm" action="${pageContext.request.contextPath }/user/login" name="actionForm"
             id="actionForm" method="post">
           <div class="info">${error }</div>
           <div class="inputbox">
               <label for="account">账号:</label>
               <input type="text" class="input-text" id="account" name="account" placeholder="请输入账号" required/>
           </div>
           <div class="inputbox">
               <label for="password">密码:</label>
               <input type="password" id="password" name="password" placeholder="请输入密码" required/>
           </div>

           <div class="subBtn">
               <input type="submit" value="登录"/>
               <input type="reset" value="重置"/>
           </div>
       </form>
   </section>
</section>
</body>
</html>
3.3.14 frame.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@include file="/WEB-INF/jsp/common/head.jsp"%>
   <div class="right">
       <img class="wColck" src="${pageContext.request.contextPath }/statics/images/clock.jpg" alt=""/>
       <div class="wFont">
           <h2>${userSession.realName }</h2>
           <p>欢迎来到724便利店管理系统!</p>
       </div>
   </div>
</section>
<%@include file="/WEB-INF/jsp/common/foot.jsp" %>
3.3.15 common/head.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>	
<!DOCTYPE html>
<html>
<head lang="en">
   <meta charset="UTF-8">
   <title>724便利店管理系统</title>
   <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/statics/css/style.css" />
   <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/statics/css/public.css" />
</head>
<body>
<!--头部-->
   <header class="publicHeader">
       <h1>724便利店管理系统</h1>
       <div class="publicHeaderR">
           <p><span style="color: #fff21b"> ${userSession.realName }</span> , 欢迎光临!</p>
           <a href="${pageContext.request.contextPath }/user/logout">登出</a>
       </div>
   </header>
<!--时间-->
   <section class="publicTime">
       <span id="time">2019年1月1日 11:11  星期一</span>
       <a href="#">为了保证正常使用,请使用IE10.0以上版本!</a>
   </section>
<!--主体内容-->
<section class="publicMian">
    <div class="left">
        <h2 class="leftH2"><span class="span1"></span>菜单 <span></span></h2>
        <nav>
            <ul class="list">
             <li ><a href="${pageContext.request.contextPath }/jsp/storageRecord.do?method=query">入库记录信息</a></li>
             <li><a href="${pageContext.request.contextPath }/jsp/supplier.do?method=query">供货商信息</a></li>
             <li><a href="${pageContext.request.contextPath }/jsp/user.do?method=query">用户信息</a></li>
             <li><a href="${pageContext.request.contextPath }/jsp/sysUser/updatePassword.jsp">修改密码</a></li>
             <li><a href="${pageContext.request.contextPath }/user/logout">退出系统</a></li>
            </ul>
        </nav>
    </div>
    <input type="hidden" id="path" name="path" value="${pageContext.request.contextPath }"/>
    <input type="hidden" id="referer" name="referer" value="<%=request.getHeader("Referer")%>"/>
 <!-- </section> -->
3.3.16 common/foot.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<div class="div_footer">
	<footer class="footer" style="height: 30px">
	    版权归Aiden所有
	</footer>
</div>
<script type="text/javascript" src="${pageContext.request.contextPath }/statics/js/time.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/statics/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/statics/js/common.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/statics/calendar/WdatePicker.js"></script>
</body>
</html>
3.3.17 maven pom.xml配置
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.19</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
    <!-- 添加JSTL标准标签库的Maven依赖-->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>
3.3.18 Constants 系统静态常量
package com.aiden.springmvc.cvs.utils;

/**
 * @author Aiden
 */
public interface Constants {
    /**
     * 用户Session Key
     */
    String USER_SESSION = "userSession";
    /**
     * 系统信息
     */
    String SYS_MESSAGE = "message";
    /**
     * 分页时每页显示的行数
     */
    int pageSize = 5;
}

四、静态资源文件的引用

4.1静态资源无法正常加载的原因
  • 为什么页面中没有相应的样式和图片?

在这里插入图片描述

分析:

  • web.xml中配置的DispatcherServlet请求映射为 “/”
  • 怎么解决?

方案:

<mvc:resources/>标签

  1. mapping:将静态资源映射到指定的路径下
  2. location:本地静态资源文件所在的目录
<mvc:resources mapping="/statics/**" location="/statics/" />

访问测试:

在这里插入图片描述


4.2登录功能优化

需求说明
1、登录成功后的当前用户信息需要保存在session中
2、如果登录失败,除了页面跳转到登录页,还需在页面上进行错误提示

Servlet API对象作为处理方法的入参

​ HttpSession
​ HttpServletRequest

页面上使用EL表达式显示相应信息

在这里插入图片描述

在这里插入图片描述

练习操作—改造724系统的登录、注销功能

需求说明

  1. 搭建SpringMVC+Spring+JDBC框架,并使用新的框架实现724系统的用户登录注销功能
  2. 将Spring配置文件进行拆分管理
  3. 用户登录成功后,将用户信息存储到session中并跳转到系统首页
  4. 退出登录时销毁session并跳转到登录页面
  5. 如果登录失败,须在登录页显示失败原因

五、异常处理

5.1异常处理

异常处理

  • HandlerExceptionResolver
    • resolveException()

局部异常处理

  • 仅能处理指定Controller中的异常
    • @ExceptionHandler
@Controller
@RequestMapping("/user")
public class SysUserController {
	
private Logger logger = Logger.getLogger(SysUserController.class);

	/**
	 * 一个抛出异常的接口
	 * @param account
	 * @param password
	 * @return
	 */
	@RequestMapping("/exLogin")
	public String exLogin(String account, String password){
		logger.debug("一个抛出异常的接口");
		//调用service方法,进行用户匹配
		SysUser user = sysUserService.login(account,password);
		if(null == user){//登录失败
			throw new NullPointerException("空指针异常!");
		}else{
			throw new RuntimeException("用户名或者密码不正确,跳转到错误页面!");
		}
		//return "redirect:/user/toMain";
	}

	/**
	 * 捕获异常信息,跳转到error页面
	 */
	@ExceptionHandler(value={Exception.class})
	public String handlerException(Exception e, HttpServletRequest req){
		req.setAttribute("e", e);
		return "error";
	}
}
  • 视图页面 error.jsp
<body>
<h1>
	${e.message }
</h1>
</body>
5.2异常处理
  • 全局异常处理
  • 对所有异常进行统一处理
  • 配置 SimpleMappingExceptionResolver ,发生异常时使用对应的视图error报告异常
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionAttribute" value="ex"></property>
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">error</prop>
        </props>
    </property>
</bean>
  • 视图页面 error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>错误信息页面</title>
</head>
<body>
<h6>异常信息:<span style="color: red">${requestScope.ex}</span></h6>
</body>
</html>

六、改造用户列表查询功能

6.1需求说明
  • 原有业务不变,实现技术引入Spring和Spring MVC框架
  • 改造用户管理功能模块中的用户列表查询功能
    • 查询条件
      • 用户名称(模糊匹配)、用户角色(精确匹配)
    • 列表页显示字段
      • 用户名、真实姓名、角色名称、年龄、电话等
      • 分页显示数据列表

在这里插入图片描述

6.2实现步骤
  1. 改造Controller
    • SysUserController中增加查询用户列表getUserList()方法
  2. 增加异常处理
    • 增加处理异常请求的接口/user/toSysError
  3. 改造View层
    • list.jsp
      rollpage.jsp
  4. 增加sysError.jsp页面
6.3 练习—改造供货商列表查询功能

需求说明

  1. 在前面学员操作的基础上,实现供货商列表查询功能
  2. 要求可根据供货商编码、供货商名称进行模糊匹配并包含分页功能

在这里插入图片描述

七、本章总结

7.1本章总结

 [

八、监听器

8.1 ContextLoaderListener监听器作用
  1. ContextLoaderListener是一个监听器,由Spring编写并提供。

  2. ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。

  3. 配合ContextLoaderListener一起使用的,经常是context-param,用来指定Spring要加载的配置文件,比如:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             id="WebApp_ID" version="3.0">
        
        <display-name>Aiden Create Spring Web MVC</display-name>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-*.xml</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>spring-mvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>spring-mvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    </web-app>
    
    
  4. 在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

众生云海,一念初见

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

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

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

打赏作者

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

抵扣说明:

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

余额充值