38-SpringMVC

38-SpringMVC-qianfeng-笔记


文章目录


一、SpringMVC概述

Spring MVC是由Spring官方提供的基于MvC设计理念的web框架。
SpringMVC是基于Servlet封装的用于实现MWC控制的框架,实现前端和服务端的交互。

①:SpringMVC优势

  • 严格遵守了MVC分层思想
  • 采用了松耦合、插件式结构;相比较于我们封装的BaseServlet以及其他的一些MVC框架来说更灵活、更具扩展性
  • SpringMVC是基于Spring的扩展、提供了一套完善的MVC注解
  • SpringMVC在数据绑定、视图解析都提供了多种处理方式,可灵活配置
  • SpringMVC对RESTful URL设计方法提供了良好的支持

②:SpringMVC本质工作

  • 接收并解析请求
  • 处理请求
  • 数据渲染、响应请求

二、SpringMVC框架部署

①:创建Web工程

01. 创建步骤

1.使用骨架
在这里插入图片描述在这里插入图片描述 在这里插入图片描述在这里插入图片描述

在这里插入图片描述

2. 补全项目结构
在这里插入图片描述

02. 添加依赖

  • spring-context
  • spring-aspects
  • spring-jdbc
  • spring-web
  • spring-webmvc
  • spring-test
3. 添加依赖
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.18</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>5.3.18</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.3.18</version>
  <scope>test</scope>
</dependency>

03. 创建SpringMVC配置文件

  • 在resources目录下创建名为spring-servlet.xml的文件
  • 添加MVC命名空间
<?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:aop="http://www.springframework.org/schema/aop"
       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/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd 
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd    
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
    

    <context:annotation-config/>
    <!-- 启动mvc注解驱动 -->
    <mvc:annotation-driven />

    <!-- 配置扫描的包 -->
    <context:component-scan base-package="com" />
    
</beans>

04. 在web.xml中配置SpringMVC的前控制器

SpringMVC提供了一个名为DispatcherServlet的类(SpringMVCi前端控制器),用于拦截用户请求交由
SpringMVC处理

<servlet>
  <servlet-name>SpringMVC</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-servlet.xml</param-value>
  </init-param>

  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>SpringMVC</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>
在这里插入图片描述

三、SpringMVC框架使用

在SpringMVC中,我们把接收用户请求、处理用户请求的类称之为Controlelr(控制器)

①:创建控制器

01. 创建控制器类

  • 创建一个名为com.qfedu.controllers的包(包需要在Spring注解扫描的范围内)
  • 创建一个类(无需做任何的继承和实现)
  • 在类上添加@Controller注解声明此类为SpringMVC的控制器
  • 在类上添加@RequestMapping("url")声明此控制器类的请求url
@Controller
@RequestMapping("/book")
public class BookController {

}

02. 在控制器类中定义处理请求的方法

  • 在一个控制器类中可以定于多个方法处理不同的请求
  • 在每个方法上添加@RequestMapping("url")用于声明当前方法请求的url
@Controller
@RequestMapping("/book")
public class BookController {

    @RequestMapping("/add")
    public void add(){
        System.out.println("**********Book add************");
    }
    @RequestMapping("/list")
    public void list(){
        System.out.println("**********Book list************");
    }
}

03. 访问

在这里插入图片描述
注意:若无法访问 检查Tomcat路径是否修改
在这里插入图片描述在这里插入图片描述

②:静态资源配置

00. 创建前端页面

  • book-add.jsp
<%@page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>添加图书</title>
</head>
<body>
<h3>添加图书</h3>
<form action="" method="post">
    <p>图书名称:<input type="text"/></p>
    <p>图书作者:<input type="text"/></p>
    <p>图书价格:<input type="text"/></p>
    <p><input type="submit" value="提交"/></p>
</form>
</body>
</html>

在这里插入图片描述

01. /* 和 /的区别

  • /*拦截所有的HTTP请求,包括.jsP的请求,都做为控制器类的请求路径来处理
  • /拦截所有的HTTP请求,但不包括,jsp的请求,不会放行静态资源的请求(html/css/js/图片)
1. 使用/*
在这里插入图片描述
2. 使用/
在这里插入图片描述
3. 添加静态资源css样式后在访问
在这里插入图片描述

02. 静态资源放行配置

在springMVCl的配置文件,添加如下静态资源放行的配置

<!--    配置静态资源放行-->
    <mvc:resources mapping="/css/**" location="css/"/>
    <mvc:resources mapping="/js/**" location="js/"/>
    <mvc:resources mapping="/imgs/**" location="imgs/"/>
    <mvc:resources mapping="/pages/**" location="pages/"/>
在这里插入图片描述 在这里插入图片描述

③:前端提交数据到控制器

01.设置表单提交路径

book-add,jsp表单的action属性设置控制器类的url和对应方法的url的组合路径
在这里插入图片描述

02.表单提交

  • 表单提交:输入框需要提供name属性,SpringMVC控制器是通过name属性取值的
<body>
<h3>添加图书</h3>
<form action="book/add" method="post">
    <p>图书名称:<input type="text" name="bookName"/></p>
    <p>图书作者:<input type="text" name="bookAuthor"/></p>
    <p>图书价格:<input type="text" name="bookPrice"/></p>
    <p><input type="submit" value="提交"/></p>
</form>
</body>

03. URL提交

  • URL提交:<a href:="book/add?bookName=]ava">URL提交</a>

04. AJAX提交

  • AJAX提交:请求行、请求头、请求体都可以用来传值
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName = "Java";
        obj.bookAuthor = "张三";
        obj.bookPrice = 9.99;

        $.ajax({
            url:"book/add",
            type: "post",
            headers:{},
            contentType:"application/json",
            data:obj,
            success:function (res){
                console.log(res)
            }
        });
    });
</script>
在这里插入图片描述

④:控制器接收前端提交的数据

01.请求行传值

  • 表单提交
  • URL提交
  • $.ajax()请求的url传值
  • $.post()/$.get()中的{}传值
  • @RequestParam注解用于接收请求行传递的数据

前端提交数据

<form action="book/add" method="post">
    <p>图书名称:<input type="text" name="bookName"/></p>
    <p>图书作者:<input type="text" name="bookAuthor"/></p>
    <p>图书价格:<input type="text" name="bookPrice"/></p>
    <p><input type="submit" value="提交"/></p>
</form>

控制器接收数据

    // 接收请求行数据
    @RequestMapping("/add")
    public void add(@RequestParam("bookName") String bookName,
                    @RequestParam("bookAuthor") String bookAuthor,
                    @RequestParam("bookPrice") String bookPrice){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
    }

在这里插入图片描述

注意:如果控制器方法中接收数据的参数名与请求行传值的key一致
则@RequestParami注解可省略
在这里插入图片描述在这里插入图片描述

02. 请求头传值

  • ajax封装请求头数据

前端代码

<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $("#btn1").click(function () {
        $.ajax({
            url: "book/list",
            type: "post",
            headers: {
                token: "My name is Coke"
            },
            success: function (res) {
                console.log(res)
            }
        });
    });
</script>)

后端代码

    @RequestMapping("/list")
    public void list(@RequestHeader("token") String token){
        System.out.println("**********Book list************");
        System.out.println(token);
    }

在这里插入图片描述

03. 请求行和请求头同时传值

前端代码

<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $("#btn1").click(function () {
        $.ajax({
            url: "book/add?bookName=Java&bookAuthor=Coke&bookPrice=9.9",
            type: "post",
            headers: {
                token: "My name is Coke"
            },
            success: function (res) {
                console.log(res)
            }
        });
    });
</script>

后端代码

    // 接收请求行数据
    @RequestMapping("/add")
    public void add(String bookName,
                    String bookAuthor,
                    String bookPrice,
                    @RequestHeader("token") String token){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
        System.out.println("token = " + token);
    }
在这里插入图片描述

04.请求体传值

1.方式一(request输入流读数据)
  • ajax封装请求体数据

前端代码

<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName = "Java";
        obj.bookAuthor = "Coke";
        obj.bookPrice = 9.99;

        $.ajax({
            url:"book/update",
            type: "post",
            contentType:"application/json",
            data:obj,
            success:function (res){
                console.log(res)
            }
        });
    });
</script>

后端代码

    @RequestMapping("/update")
    public void update(HttpServletRequest request){
        System.out.println("**********Book update************");
        try {
            // 使用request的输入流接收请求体数据
            ServletInputStream is = request.getInputStream();
            StringBuffer buffer = new StringBuffer();
            byte[] bs = new byte[100];
            int len = -1;
            while ((len = is.read(bs)) != -1) {
                String s = new String(bs, 0, len);
                buffer.append(s);
            }
            System.out.println("buffer.toString() = " + buffer.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
在这里插入图片描述
2. 方式二(使用@RequestBody)
  • 添加依赖(@RequestBody需要将json格式数据转换成java对象)
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.13.3</version>
</dependency>
1. 创建Book类并提供get set 等方法
在这里插入图片描述
2. 前端代码
<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName = "Java";
        obj.bookAuthor = "Coke";
        obj.bookPrice = 9.99;
        var s = JSON.stringify(obj)
        $.ajax({
            url:"book/update",
            type: "post",
            contentType:"application/json",
            data:s,
            success:function (res){
                console.log(res)
            }
        });
    });
</script>
在这里插入图片描述
3. 后端代码
    @RequestMapping("/update")
    public void update(@RequestBody Book book){
        System.out.println("**********Book update************");
        System.out.println(book);
    }

在这里插入图片描述

⑤:控制器响应前端请求

01. 控制器响应同步请求

  • 同步请求:form、超链接

处理同步请求的方法的返回类型定义为String或者ModelAndView,以实现页面的跳转

1. 返回类型为String

1. 转发

1. 添加跳转后tips.jsp界面
在这里插入图片描述
2. 后端代码
    // 接收请求行数据
    @RequestMapping("/add")
    public String add(String bookName, String bookAuthor, String bookPrice){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
        return "/tips.jsp";
    }
3. 测试
在这里插入图片描述

2. 重定向

    // 接收请求行数据
    @RequestMapping("/add")
    public String add(String bookName, String bookAuthor, String bookPrice){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
        return "redirect:/tips.jsp";
    }
2.返回类型为ModelAndView

1. 转发

    // 接收请求行数据
    @RequestMapping("/add")
    public ModelAndView add(String bookName, String bookAuthor, String bookPrice){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
        ModelAndView modelAndView = new ModelAndView("/tips.jsp");
        return modelAndView;
    }

2. 重定向

    // 接收请求行数据
    @RequestMapping("/add")
    public ModelAndView add(String bookName, String bookAuthor, String bookPrice){
        System.out.println("**********Book add************");
        System.out.println("bookName = " + bookName);
        System.out.println("bookAuthor = " + bookAuthor);
        System.out.println("bookPrice = " + bookPrice);
        ModelAndView modelAndView = new ModelAndView("redirect:/tips.jsp");
        return modelAndView;
    }

02. 控制器响应异步请求

异步请求:ajax请求

1. 使用response中的输出流进行响应
  • 控制器方法的返回类型为void
  • 控制器方法添加HttpServletResponse response参数
  • 在方法中通过response获取输出流,使用流响应ajax清求
1. 前端代码
<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName = "Java";
        obj.bookAuthor = "Coke";
        obj.bookPrice = 9.99;
        var s = JSON.stringify(obj)
        $.ajax({
            url:"book/update",
            type: "post",
            contentType:"application/json",
            data:s,
            success:function (res){
                console.log(res)
            }
        });
    });
</script>
2. 后端代码
    @RequestMapping("/update")
    public void update(@RequestBody Book book, HttpServletResponse response) throws IOException {
        System.out.println("**********Book update************");
        // 使用ObjectMapper将对象转换成JSON格式字符串
        String s = new ObjectMapper().writeValueAsString(book);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.println(s);
        out.flush();
        out.close();
    }
3. 测试
在这里插入图片描述
2.直接在控制器方法返回响应的对象
  • 控制器方法的返回类型设置为响应给ajax请求的对象类型
  • 在控制器方法前添加@ResponseBody注解,将返回的对象转换成JSON响应给ajax请求
1. 后端代码(前端代码无修改)
    @RequestMapping("/update")
    @ResponseBody
    public List<Book> update() {
        System.out.println("**********Book update************");
        ArrayList<Book> books = new ArrayList<>();
        books.add(new Book(1,"Java","Coke",9.9));
        books.add(new Book(2,"Linux","KangKang",9.99));
        return books;
    }
在这里插入图片描述

⑥:控制器响应同步请求的数据传递

对于同步请求的转发响应,我们可以传递参数到转发的页面

01. 返回类型为String

1. 前端代码
在这里插入图片描述
2. 后端代码
    //1.在控制器方法中定义一个Mode1类型的参数
    //2.在return页面之前,向model中添加键值对,添加的键值对就会被传递到转发的页面
    @RequestMapping("/add")
    public String add(String bookName, String bookAuthor, Double bookPrice, Model model){
        model.addAttribute("key","value");
        model.addAttribute("book",new Book(1,"Java","Coke",9.9));
        return "/tips.jsp";
    }
    //除了使用Model对象传值外,还可以直接使用HttpServletRequest对象
    @RequestMapping("/add")
    public String add(String bookName, String bookAuthor, Double bookPrice, HttpServletRequest request){
        request.setAttribute("key","value");
        request.setAttribute("book",new Book(1,"Java","Coke",9.9));
        return "/tips.jsp";
    }
3. 测试
在这里插入图片描述

02. 返回类型ModelAndView

    @RequestMapping("/add")
    public ModelAndView add(String bookName, String bookAuthor, Double bookPrice){
        ModelAndView model = new ModelAndView("/tips.jsp");
        model.addObject("key","value");
        model.addObject("book",new Book(1,"Java","Coke",9.9));
        return model;
    }

⑦:中文乱码问题

01. 前端编码

  • JSP 页面编码设置
<%@page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
  • HTML页面编码设置
<meta charset="UTF-8">

02.设置服务器编码设置

<Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" URIEncoding="UTF-8"/>
tomcat/conf/server.xml
在这里插入图片描述

03. 后端(SpringMVC)编码设置

    <filter>
        <filter-name>EncodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
<filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
在这里插入图片描述

04. 测试

中文乱码已解决
在这里插入图片描述

四、SpringMVC的请求处理流程

①:请求处理流程

SpringMVC通过前端控制器(DispatcherServlet)拦截并处理用户请求的

在这里插入图片描述

②:SpringMVC的核心组件

  • DispatcherServlet前端控制器、总控制器
    • 作用:接收请求, 协同各组件工作、响应请求
  • HandlerMapping 处理器映射(可配置)
    • 作用:负责根据用户请求的URL找到对应的Handler(Controller)
  • Handler Adapter处理器适配器
    • 作用:按照处理器映射器解析的用户请求的调用链,通过适配器模式完成Handler的调用
  • Handler处理器/控制器
    • 由工程师根据业务的需求进行开发
    • 作用:处理请求
  • ModelAndView视图模型
    • 作用:用于封装处理器返回的数据以及相应的视图
    • ModelAndView = Model + View
  • ViewResolver视图解析器(可配置)
    • 作用:对ModelAndViewi进行解析
  • View视图
    • 作用:完成数据渲染

③:处理器映射器

不同的处理器映射器对UL处理的方式也不相同,使用对应的处理器映射器之后我们的前端请求规则也需要发生相应的变化
SpringMVC提供的处理器映射器:

  • BeanNameUrlHandlerMapping根据控制器的ID访问控制器
  • SimpleUrlHandlerMapping根据控制器配置的URL访问(默认)

配置处理器映射器:

  • SpringMVC的配置文件中通过bean标签声明处理器映射器
  • 配置BeanNameUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  • 配置SimpleUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/aaa">bookController</prop>
        </props>
    </property>
</bean>

④:视图解析器

Spring提供了多个视图解析器

  • UrlBasedViewResolver
  • InternalResourceViewResolver
  • UrlBasedViewResolver需要依赖jstl
    • 添加依赖
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  • 配置视图解析器 UrlBasedViewResolver
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
   <property name="viewClass" value="com.fasterxml.jackson.annotation.JsonView"/>
   <property name="prefix" value="/"/>
   <property name="suffix" value=".jsp"/>
</bean>
  • 配置视图解析器 InternalResourceViewResolver
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>
测试
在这里插入图片描述

五、日期格式处理

①:使用对象来接收数据

1. 创建一个新的类
在这里插入图片描述
2. 修改访问路径
在这里插入图片描述
3. 测试(注意:实体类的属性名要和前端输入框的name属性名称一样)
在这里插入图片描述

②:日期格式处理

如果前端需要输入日期数据,在控制器中转换成Date对象,SpringMVC要求前端输入的日期格式必须为
yyyy/MM/dd
如果甲方要求日期格式必须为指定的格式,而这个指定格式SpringMVC不接受,该如何处理呢?

  • 自定义日期转换器

01. 自定义日期转换器

1. 添加一个日期属性Data(提供构造器及get set等方法)
在这里插入图片描述
2.添加输入框
在这里插入图片描述
3. 创建一个自定义日期转换器
// 1.创建一个类实现Converter接口,泛型指定从什么类型转换为什么类型
//  2.实现convert转换方法
public class MyDataConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
        Date date = null;
        try {
            date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
在这里插入图片描述

02. 配置自定义日期转换器

    <!-- 启动mvc注解驱动 -->
    <mvc:annotation-driven conversion-service="converterFactory"/>

    <bean id="converterFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.it.utils.MyDataConverter"/>
            </set>
        </property>
    </bean>
在这里插入图片描述
测试
在这里插入图片描述

六、文件上传

①:SpringMvc框架部署

  • 基于Mavent创建web工程

步骤 略~

  • 添加SpringMVC所需的依赖
    • Spring:context aspects jdbc test web webmvc jackson
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.3.18</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.3</version>
    </dependency>
        <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
    </dependency>
  • 创建SpringMVC配置文件
  • 在web.Xml中配置SpringMVC的前端控制器
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-servlet.xml</param-value>
    </init-param>
</servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  • 在web.ml中配置SpringMVC的编码过滤器

  • 配置springmvci静态资源处理策骼

    <context:component-scan base-package="com.it"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/imgs/**" location="/imgs/"/>

②:案例准备

01. 创建index.jsp(首页面)

<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
    <body>
        <table width="100%" height="700">
            <tr>
                <td width="200" style="border-right: lightblue 2px solid; background: rgba(255,0,0,0.1)">
                    <ul>
                        <li><a href="book-add.jsp" target="mainFrame">添加图书</a> </li>
                        <li><a href="">图书列表</a></li>
                    </ul>
                </td>
                <td>
                    <iframe name="mainFrame" width="100%" height="700" frameborder="0"></iframe>
                </td>
            </tr>
            <tr></tr>
        </table>
    </body>
</html>

02. 创建book-add.jsp(图书添加页面)

<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
    <body>
        <h4>添加图书信息</h4>
        <form action="">
            <p>图书名称:<input type="text" name=""></p>
            <p>图书作者:<input type="text" name=""></p>
            <p>图书价格:<input type="text" name=""></p>
            <p>图书封面:<input type="file" name=""></p>
            <p><input type="submit" value="提交"></p>
        </form>
    </body>
</html>

03.创建tips.jsp页面

<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
    <body>

    </body>
</html>

04.设置index.jsp为默认页面

  • 在web.xml添加以下配置
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

05. 创建BookConverter类

@Controller
@RequestMapping("/book")
public class BookConverter {

    @RequestMapping("/add")
    public String addBook(){
        System.out.println("*************Book add***************");
        return "/tips.jsp";
    }
}
在这里插入图片描述

③:文件上传实现

01.创建实体类

public class Book {
    private int bookId;
    private String bookName;
    private String bookAuthor;
    private double bookPrice;
    private String bookImg;
 }
在这里插入图片描述

02. 前端提交文件

  • 表单提交方式必须为post
  • 表单entype属性设置为multipart/form-data
    <body>
        <h4>添加图书信息</h4>
        <form action="book/add" method="post" enctype="multipart/form-data">
            <p>图书名称:<input type="text" name="bookName"></p>
            <p>图书作者:<input type="text" name="bookAuthor"></p>
            <p>图书价格:<input type="text" name="bookPrice"></p>
            <p>图书封面:<input type="file" name="imgFile"></p>
            <p><input type="submit" value="提交"></p>
        </form>
    </body>

03.控制器接收数据和文件

SpringMVC处理上传文件需要借助于CommonsMultipartResolver文件解析器

  • 添加依赖 commons-io commons-fileupload
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.11.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
  • 在spring-servlet.xml中配置文件解析器
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10240000"/>
        <property name="maxInMemorySize" value="102400"/>
        <property name="defaultEncoding" value="utf-8"/>
    </bean>
  • 空制器接收文件
    • 在处理文件上传的方法中定义一个MultiPartFile类型的对象,就可以接受图片了
在这里插入图片描述

04.保存数据(图片)

@Controller
@RequestMapping("/book")
public class BookConverter {

    @RequestMapping("/add")
    public String addBook(Book book, MultipartFile imgFile, HttpServletRequest request) throws IOException {
        System.out.println("*************Book add***************");
        // imgFile 就表示上传的图片
        // 1. 截取上传文件的后缀名,生成新的文件名
        String originalFilename = imgFile.getOriginalFilename();
        String ext = originalFilename.substring(originalFilename.lastIndexOf(".")); // .png
        String filename = System.currentTimeMillis() + ext;

        // 2. 获取imgs目录在服务器中的路径
        String dir = request.getServletContext().getRealPath("imgs");
        String savePath = dir + "/" + filename;

        // 3. 保存文件
        imgFile.transferTo(new File(savePath));

        // 4.将图片的访问路径设置到book对象中
        book.setBookImg("imgs/" + filename);

        // 5.调用service保存book到数据库 略~~
        return "/tips.jsp";
    }
}
1. 在imgs路径下放一个文件,否则空文件不会被加载
在这里插入图片描述
2.在tips中添加以下代码(显示数据)
<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
    <body>
        图书名称:${book.bookName}
        <hr>
        图书作者:${book.bookAuthor}
        <hr>
        图书价格:${book.bookPrice}
        <hr>
        图书封面:${book.bookImg}
        <hr>
    </body>
</html>
3. 测试
在这里插入图片描述

七、 文件下载

①:显示文件列表

1.在BookConverter类中添加查询方法(查询图片列表)
    @RequestMapping("list")
    @ResponseBody
    public String[] listImgs(HttpServletRequest request){
        // 1. 从imgs目录下获取所有的图片信息
        String path = request.getServletContext().getRealPath("imgs");
        File imgDir = new File(path);
        String[] fileName = imgDir.list();
        return fileName;
    }
2. 添加文件list.jsp
<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
<head>
    <title>图书列表</title>
</head>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous">

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
    <body>
        <h4>图书列表</h4>
        <script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
        <script type="text/javascript">
            $.get("book/list",function(res) {
                for (let i = 0; i < res.length; i++) {
                    var fn = res[i];
                    var htmlStr = "<div class='col-lg-2  col-md-3 col-sm-4 col-xm-6'><div class='thumbnail'><img src='imgs/"+fn+"' alt='...'><div class='caption'><p><a href='#' class='btn btn-primary' role='button'>下载</a></p></div></div></div>"
                    $("#container").append(htmlStr);
                }
            },"json")
        </script>

        <div class="row" id="container">

        </div>
    </body>
</html>
3. 修改index.jsp代码
在这里插入图片描述
4. 测试
在这里插入图片描述

②:文件下载实现

1. BookConverter中添加一个下载方法
@RequestMapping("download")
public void downloadImg(String fname, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 从imgs目录找到当前文件
    String path = request.getServletContext().getRealPath("imgs");
    String filePath = path + "/" +fname;
    FileInputStream inputStream = new FileInputStream(filePath);
    ServletOutputStream outputStream = response.getOutputStream();

    response.setContentType("application/exe");
    response.addHeader("Content-Disposition","attachment;filename="+fname);

    IOUtils.copy(inputStream,outputStream);
}
在这里插入图片描述
2. 在list.jap中添加下载URL
在这里插入图片描述

八、统一异常处理

在我们的应用系统运行的过程中,可能由于运行环境、用户操作、资源不足等各方面的原因导致系统出现异常(HTTP状态异常、Exception);如果系统出现了异常,这些异常将会通过浏览器呈现给用户,而这种异常的显示是设有必要,因此我们可以在服务器进行特定的处理一当系统出现异常之后,呈现给用户一个统一的、可读的的异常提示页面。

①:HTTP异常状态统一处理

HTTP Status 404

  • 创建一个用于进行异常提示的页面:404.jsp
<%@page contentType="text/html; charset=utf-8" pageEncoding="UTF-8" language="java" %>
<html>
<head>
</head>
    <body>
        您的访问地址有误,请检查....
    </body>
</html>

  • 在web.xml中进行配置:
    <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>
测试:(访问一个不存在的地址)
在这里插入图片描述

②:Java代码异常的统一处理

01. 基于Servlet

  • 创建异常提示页面:err.jsp
  • 在web.xml中进行配置
<error-page>
    <exception-type>java.lang.NumberFormatException</exception-type>
    <location>/err.jsp</location>
</error-page>

02. SpringMVC处理

1. 创建一个异常处理类
public class MyExceptionHandler {

    // 空指针异常
    @ExceptionHandler(NullPointerException.class)
    public String nullHandler(){
        return "/err1.jsp";
    }

    // 数据格式错误异常
    @ExceptionHandler(NumberFormatException.class)
    public String formatHandler(){
        return "/err2.jsp";
    }
}
2. 针对不同的异常展示不同的jsp页面
在这里插入图片描述

九、拦截器

①:拦截器介绍

SpringMVC提供的拦截器就类似于Servlet–api中的过滤器,可以对控制器的请求进行拦截实现相关的预处理和后处理。

  • 过滤器
    • 是Servlet规范的一部分,所有的web项目都可以使用
    • 过滤器在web.xml配置(可以使用注解),能够拦截所有web清求
  • 拦截器
    • 是SpringMVC框架的实现,只有在SpringMVC框架中才能使用
    • 拦截器在SpringMVC配置文件进行配置,不会拦截SpringMVC放行的资源(jsp\html\css.…)

②:自定义拦截器

01.创建拦截器

public class MyInterceptor1 implements HandlerInterceptor{
    // 预处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("***********预处理***********");
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            if ("bookName".equals(name)){
                return true;
            }
        }
        response.setStatus(400);
        return false;
    }
    
    // 后处理
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("***********后处理***********");
        modelAndView.addObject("tips","这是通过拦截器的后处理添加的数据");
    }
    
}

02. 配置拦截器

    <mvc:interceptors>
        <mvc:interceptor>
<!--            此处可以配置多个拦截条件(当前只拦截query和add方法)-->
            <mvc:mapping path="/book/query"/>
            <mvc:mapping path="/book/add"/>
            
<!--            此处配置为拦截student下的所有方法除了add方法-->
            <mvc:mapping path="/student/**"/>
            <mvc:exclude-mapping path="/student/add"/>
            
            <bean class="com.it.utils.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>

03.添加控制器方法

在BookConverter类中添加以下方法
    @RequestMapping("query")
    public String query(String bookName){
        System.out.println(bookName);
        Book book = new Book();
        book.setBookName(bookName);
        return "/tips.jsp";
    }
在这里插入图片描述 在这里插入图片描述

③:拦截器链

将多个拦截器按照一定的顺序构成一个执行链

在这里插入图片描述

十、SSM整合

①:创建Web项目

01. 创建web工程

(完成maven工程web项目结构)步骤略

02. 添加web项目依赖

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

03.配置Tomcat运行环境

在这里插入图片描述

②:部署MyBatis

01. 添加MyBatis依赖

<!--    mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>
<!--    mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
<!--    lombok-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
      <scope>provided</scope>
    </dependency>

02. 创建mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

</configuration>

③:部署Spring、SpringMVC

01.添加依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.18</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>5.3.18</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.3.18</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.13.3</version>
</dependency>

02.创建Spring配置(多个文件分开配置)

  • spring-context.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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

<!--    声明使用注解-->
    <context:annotation-config/>

    <!-- 配置扫描的包 -->
    <context:component-scan base-package="com.it"/>
</beans>
  • spring-mvc.xml进行mvc相关的配置,例如静态资源配置、拦截器配置等
<?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"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 启动mvc注解驱动 -->
    <mvc:annotation-driven/>

</beans>
  • spring-mybatis.xml进行Spring-与MyBatis整合相关的配置
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
    
</beans>

④:配置SpringMvc前端控制器

  • 在web.xml进行配置
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

⑤:整合配置(IOC)

01.导入mybatis-spring依赖

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

02.配置druid连接池

  • 添加druid依赖
 <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.2.8</version>
 </dependency>
  • 创建druid.properties并配置
druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/db_mybatis_demo2?characterEncoding=utf-8
druid.username=root
druid.password=root

## 连接池参数
druid.pool.init=1
druid.pool.minIdle=3
druid.pool.maxActive=20
druid.pool.timeout=30000
  • 在spring-mybatis.xml配置数据源
<!--        加载druid.properties配置文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
    
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
        
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
     </bean>

03.配置SqlSessionFactory

  • 在spring-mybatis.xml进行配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="druidDataSource"/>
    <property name="mapperLocations" value="classpath:mappers/*.xml"/>
    <property name="typeAliasesPackage" value="com.it.beans"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
在这里插入图片描述

04.配置MapperScannerConfigurer

<!--    作用:将dao包中所有的类创建成bean对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.it.dao"/>
    </bean>
在这里插入图片描述

⑥:整合配置(AOP)

使用Spring提供的事务管理完成DAO操作的事务管理

  • 基于注解的事务管理配置:
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

⑦:整合测试

01.完成User的查询操作

  • 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private int userId;
    private String userName;
    private String userPwd;
    private String realName;
    private String userImg;
}
在这里插入图片描述
  • 在DAO包中创建接口
public interface UserDAO {
    User queryUserByName(String userName);
}
在这里插入图片描述
  • 在Mappers文件下创建映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.it.dao.UserDAO">

    <resultMap id="UserMap" type="User">
        <id column="user_id" property="userId"/>
        <result column="user_name" property="userName"/>
        <result column="user_pwd" property="userPwd"/>
        <result column="user_realname" property="realName"/>
        <result column="user_img" property="userImg"/>
    </resultMap>

    <select id="queryUserByName" resultMap="UserMap">
        select user_id,user_name,user_pwd,user_realname,user_img
        from users
        where user_name= #{userName}
    </select>

</mapper>

02. 对DAO单元测试

  • 添加junit、spring-test(前面已经导入过)依赖
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  • 创建测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml",
                       "classpath:spring-mvc.xml",
                       "classpath:spring-mybatis.xml"})
public class UserDAOTest {

    @Autowired
    private UserDAO userDAO;

    @Test
    public void queryUserByName() {
        User user = userDAO.queryUserByName("李四");
        System.out.println(user);
    }
}
在这里插入图片描述

03.对Service单元测试

1. 创建接口方法
public interface UserService {
    User checkLogin(String username, String password);
}
在这里插入图片描述
2. 创建接口实现类
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    @Transactional
    public User checkLogin(String username, String password) {
        User user = userDAO.queryUserByName("李四");
        if (user != null & user.getUserPwd().equals(password)){
            return user;
        }
        return null;
    }
}
在这里插入图片描述
3. 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml",
        "classpath:spring-mvc.xml",
        "classpath:spring-mybatis.xml"})
public class UserServiceTest {

    @Resource
    private UserService userService;

    @Test
    public void checkLogin() {
        User user = userService.checkLogin("李四", "123123");
        System.out.println(user);
    }
}
在这里插入图片描述

⑧:整合Controller

1. 创建UserController
@Controller
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @RequestMapping("/login")
    public String login(String username, String password, HttpServletRequest request){
        User user = userService.checkLogin(username, password);
        if (user == null){
            request.setAttribute("tips","用户名或密码错误!");
            return "/login.jsp";
        }else {
            request.getSession().setAttribute("user",user);
            return "/index.jsp";

        }
    }
}
在这里插入图片描述
2. 创建index.jsp页面
<%@page contentType="text/html;charset=utf-8" language="java" pageEncoding="UTF-8" %>

<html>
<head>

    <title>Title</title>
</head>
<body>
<h3>这是主页面~</h3>
<h4>Hello ${user.userName}~~</h4>
</body>
</html>
3. 创建login.jsp页面
<%@page contentType="text/html;charset=utf-8" language="java" pageEncoding="UTF-8" %>

<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
<h3>登录页面</h3>
${tips}
<form action="user/login" method="post">
    <p>账号:<input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <p><input type="submit" value="登录"></p>
</form>
</body>
</html>
4. 测试
在这里插入图片描述

十一 纯注解开发(补)

①:使用注解开发(入门案例)

在这里插入图片描述

1. 导入依赖
<!--    1. 导入坐标springmvc  servlet-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
2. 创建控制器类
// 2.1 使用Controller定义bean
@Controller
// 2.2 设置当前操作的访问路径
@RequestMapping("user")
public class UserController {

    @RequestMapping("add")
    // 2.3 设置返回类型
    @ResponseBody
    public String addUser(String username){
        System.out.println("*******User  add*******"+username);
        return "{'module':'username'}";
    }
}
在这里插入图片描述
3. 创建springmvc的配置类,加载controller对应的bean
// 3. 创建springmvc的配置类,加载controller对应的bean
@Configuration
@ComponentScan("com.it.controller")
public class SpringMvcConfig {
}
在这里插入图片描述
4. 4. 定义一个serlvet容器启动的配置类,在里面加载spring的配置
// 4. 定义一个serlvet容器启动的配置类,在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {

    // 该方法:加载springMvc容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMvcConfig.class);
        return context;
    }
    // 该方法:设置哪些请求归属springmvc处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    // 该方法:加载spring容器的配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}
在这里插入图片描述
5. 测试
在这里插入图片描述

②:bean加载控制

在这里插入图片描述

1. 设定扫描范围为精确范围
在这里插入图片描述
2. 排除掉controller包内的bean
在这里插入图片描述
3. 不区分Spring与SpringMVC的环境,加载到同一个环境中
// 4. 定义一个serlvet容器启动的配置类,在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {

    // 该方法:加载springMvc容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMvcConfig.class);
        return context;
    }

    // 该方法:加载spring容器的配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringConfig.class);
        return context;
    }

    // 该方法:设置哪些请求归属springmvc处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
在这里插入图片描述
4. 不区分Spring与SpringMVC的环境,加载到同一个环境中(简化版)
// 4. 定义一个serlvet容器启动的配置类,在里面加载spring的配置
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
在这里插入图片描述

③:PostMan工具

官网:[https://www.postman.com/](https://www.postman.com/)
在这里插入图片描述

④:postman发送get和post请求

在这里插入图片描述

1. get请求
在这里插入图片描述 在这里插入图片描述
2. post请求
在这里插入图片描述在这里插入图片描述
3. 解决post请求中文乱码
    // 乱码处理

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("utf-8");
        return new Filter[] {filter};
    }
在这里插入图片描述 在这里插入图片描述

⑤post发送json数据

在这里插入图片描述

1. 导入jackson-databind依赖
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.3</version>
    </dependency>
2. 在springmvc配置文件中添加@EnableWebMvc
在这里插入图片描述

01. 集合参数(Json)

    // 集合参数(json)
    @RequestMapping("list")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> lists){
        System.out.println("lists = " + lists);
        return lists.toString();
    }
在这里插入图片描述在这里插入图片描述

02. pojo参数(Json)

    // pojo参数(json)
    @RequestMapping("users")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User users){
        System.out.println("users = " + users);
        return "users = " + users;
    }
在这里插入图片描述在这里插入图片描述

03. pojo集合参数

    // pojo集合参数(json)
    @RequestMapping("listUser")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> users){
        System.out.println("users = " + users);
        return "users = " + users;
    }
在这里插入图片描述在这里插入图片描述

04. 日期参数

    // 日期参数
    @RequestMapping("date")
    @ResponseBody
    public String dateParam(Date date,
                            @DateTimeFormat(pattern = "yyyy-MM-dd") Date date2,
                            @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3){
        System.out.println("date = " + date);
        System.out.println("date2 = " + date2);
        System.out.println("date3 = " + date3);
        return date+","+date2+","+date3;
    }
在这里插入图片描述在这里插入图片描述

⑤:REST风格

在这里插入图片描述

01. 入门案例

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

1. 在BookController类中添加增删改查方法
@Controller
public class BookController {

    @RequestMapping(value = "books", method = RequestMethod.POST)
    @ResponseBody
    public String add(){
        System.out.println("Book  add *****");
        return "Book  add *****";
    }

    @RequestMapping(value ="books/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("Book  delete *****" + id);
        return "Book  delete *****" + id;
    }

    @RequestMapping(value ="books", method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody Book book){
        System.out.println("Book  update *****" + book);
        return "Book  update *****" + book;
    }

    @RequestMapping(value ="books/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id){
        System.out.println("Book  getById *****" + id);
        return "Book  getById *****" + id;
    }
}
在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

02.RESTful快速开发

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

@RestController
@RequestMapping("books")
public class BookController2 {

    @PostMapping
    public String add(){
        System.out.println("Book  add *****");
        return "Book  add *****";
    }

    @DeleteMapping("{id}")
    public String delete(@PathVariable Integer id){
        System.out.println("Book  delete *****" + id);
        return "Book  delete *****" + id;
    }

    @PutMapping
    public String update(@RequestBody Book book){
        System.out.println("Book  update *****" + book);
        return "Book  update *****" + book;
    }

    @GetMapping("{id}")
    public String getById(@PathVariable Integer id){
        System.out.println("Book  getById *****" + id);
        return "Book  getById *****" + id;
    }
}

⑥:基于RESTful页面数据交互

01.数据准备

1. 创建实体类
在这里插入图片描述
2. 创建config配置文件
在这里插入图片描述
@Controller
@ComponentScan("com.it.controller")
@EnableWebMvc
public class SpringMvcConfig {
}

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    // 乱码处理
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("utf-8");
        return new Filter[]{filter};
    }
}

2. 创建Controller类
@RestController
@RequestMapping("/books")
public class BookController {

    @PostMapping
    public String save(@RequestBody Book book){
        System.out.println("*******Book  save*******" + book);
        return "*******Book  save*******" + book;
    }

    @GetMapping
    public List<Book> getAll(){
        ArrayList<Book> bookList = new ArrayList<>();

        Book book1 = new Book();
        book1.setType("计算机");
        book1.setName("Java核心");
        book1.setDescription("从入门到精通~");
        bookList.add(book1);

        Book book2 = new Book();
        book2.setType("计算机");
        book2.setName("Linux核心");
        book2.setDescription("从入门到精通~");
        bookList.add(book2);

        return bookList;
    }


}

3. 测试
在这里插入图片描述在这里插入图片描述

02. 放行静态资源

在这里插入图片描述

1
在这里插入图片描述
2. 创建SpringMvcSupport类
在这里插入图片描述
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/pages/**","/pages/");
        registry.addResourceHandler("/js/**","/js/");
        registry.addResourceHandler("/css/**","/css/");
        registry.addResourceHandler("/plugins/**","/plugins/");
    }
}

十二、纯注解SSM整合(补)

①:整合配置

在这里插入图片描述

1. 导入依赖
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.3.18</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.3</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>
2. 创建配置文件
在这里插入图片描述
@Configuration
@ComponentScan("com.it.service")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
public class SpringConfig {
}
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource datasource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
public class MyBatisConfig {

    @Bean
    public SqlSessionFactoryBean sessionFactory(DataSource dataSource){
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setTypeAliasesPackage("com.it.domain");
        return factoryBean;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.it.dao");
        return configurer;
    }
}
@Configuration
@ComponentScan("com.it.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_mybatis_demo2?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

②:功能模块开发

1. 创建数据表
create table books(
    id int auto_increment primary key ,
    type varchar(20) not null ,
    name varchar(50) not null ,
    description varchar(255)
)
insert into books (type, name, description)
VALUES ('计算机理论', 'Spring?实战第5版', 'Spring入门经典教程,深入理解Spring.原理技术内幕'),
       ('计算机理论', 'Spring5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想'),
       ('计算机理论', 'Spring5设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式'),
       ('计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手'),
       ('计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握)ava基础的读者'),
       ('计算机理论', 'Java核心技术卷1基础知识(原书第11版)', 'Core Java第11版,Jolt大奖获奖作品,针对ava SE9、10、11全面更新'),
       ('计算机理论', '深入理解Java虚拟机', '5个维度全面剖析VM,大厂面试知识点全覆盖'),
       ('计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉'),
       ('计算机理论', '零基础学ava(全彩版)', '零基础自学编程的入门图书,由浅入深,详解)va语言的编程思想和核心技术'),
       ('市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中'),
       ('市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍'),
       ('市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');
2. 创建实体类
在这里插入图片描述
3. 定义BookDao接口方法
public interface BookDao {

    @Insert("insert into books (type, name, description) values (#{type}, #{name}, #{description})")
    public int save(Book book);

    @Update("update books set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
    public int update(Book book);

    @Delete("delete from books where id = #{id}")
    public int delete(Integer id);

    @Select("select * from books where id = #{id}")
    public Book getById(Integer id);

    @Select("select * from books")
    public List<Book> getAll();
}
4. 定义BookService接口方法
public interface BookService {

    public boolean addBook(Book book);

    public boolean updateBook(Book book);

    public boolean deleteBook(Integer id);

    public Book getBookById(Integer id);

    public List<Book> getAllBooks();
}
5. 创建BookService实现类BookServiceImpl
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    @Override
    public boolean addBook(Book book) {
        return bookDao.save(book) > 0;
    }

    @Override
    public boolean updateBook(Book book) {
        return bookDao.update(book) > 0;
    }

    @Override
    public boolean deleteBook(Integer id) {
        return bookDao.delete(id) > 0;
    }

    @Override
    public Book getBookById(Integer id) {
        return bookDao.getById(id);
    }

    @Override
    public List<Book> getAllBooks() {
        return bookDao.getAll();
    }
}
5.2 IDEA检查自动装配报错
在这里插入图片描述在这里插入图片描述
6. 创建BookController与页面交互
@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookService bookService;

    @PostMapping
    public boolean addBook(@RequestBody Book book) {
        return bookService.addBook(book);
    }
    @PutMapping
    public boolean updateBook(@RequestBody Book book) {
        return bookService.updateBook(book);
    }

    @DeleteMapping("{id}")
    public boolean deleteBook(@PathVariable Integer id) {
        return bookService.deleteBook(id);
    }
    @GetMapping("/{id}")
    public Book getBookById(@PathVariable Integer id) {
        return bookService.getBookById(id);
    }
    @GetMapping
    public List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }
}

③:接口测试

1. 业务层接口测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {

    @Autowired
    private BookService bookService;

    @Test
    public void addBook() {
        Book book = new Book(0,"计算机类","Java核心卷Ⅱ","从入门到精通");
        boolean b = bookService.addBook(book);
        System.out.println(b);
    }

    @Test
    public void updateBook() {
        Book book = new Book(13,"计算机类","Java核心卷Ⅲ","从入门到秃顶");
        bookService.updateBook(book);
    }

    @Test
    public void deleteBook() {
        boolean b = bookService.deleteBook(13);
        System.out.println(b);
    }

    @Test
    public void getBookById() {
        Book book = bookService.getBookById(1);
        System.out.println(book);
    }

    @Test
    public void getAllBooks() {
        List<Book> allBooks = bookService.getAllBooks();
        for (int i = 0; i < allBooks.size(); i++) {
            System.out.println(allBooks.get(i));
        }
    }
}
2. 表现层接口测试
在这里插入图片描述在这里插入图片描述

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

④:事务管理

1. 开启注解事务驱动
在这里插入图片描述
2. 创建事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }
在这里插入图片描述
3.
在这里插入图片描述

⑤:乱码处理

    // 乱码处理

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("utf-8");
        return new Filter[]{filter};
    }
在这里插入图片描述

⑥:表现层与前端数据协议实现

1. 在controller包下创建Result用于封装数据
在这里插入图片描述
2. 在controller包下创建Code类定义所有的状态码值
public class Code {
    // 定义成功的状态码
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    // 定义失败的状态码
    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;
}
3. 修改BookController中的代码
@RestController
@RequestMapping("/books")
@Transactional
public class BookController {

    @Autowired
    private BookService bookService;

    @PostMapping
    public Result addBook(@RequestBody Book book) {
        boolean flag = bookService.addBook(book);
        return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
    }
    @PutMapping
    public Result updateBook(@RequestBody Book book) {
        boolean flag = bookService.updateBook(book);
        return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);
    }

    @DeleteMapping("{id}")
    public Result deleteBook(@PathVariable Integer id) {
        boolean flag = bookService.deleteBook(id);
        return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
    }
    @GetMapping("/{id}")
    public Result getBookById(@PathVariable Integer id) {
        Book book = bookService.getBookById(id);
        Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
        String msg = book != null ? "" : "数据查询失败,请重试!";
        return new Result(code, book,msg);
    }
    @GetMapping
    public Result getAllBooks() {
        List<Book> bookList = bookService.getAllBooks();
        Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
        String msg = bookList != null ? "" : "数据查询失败,请重试!";
        return new Result(code, bookList,msg);
    }
}
4. 测试
在这里插入图片描述在这里插入图片描述在这里插入图片描述

⑦:异常处理

01. 异常处理器

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

1. 在controller包下创建ProjectExceptionAdvice类
@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(Exception.class) // 指定处理哪种类型的异常
    public Result doException(){
        return new Result(666,null,"🤭🤭出异常啦🎶🎶");
    }
}
2. 测试(在根据id查询Book方法中制造一个异常)
在这里插入图片描述

02. 异常处理方案

在这里插入图片描述

1. 创建exception包并在包内创建SystemException(系统异常)类和SystemException(业务异常)类
在这里插入图片描述
public class BusinessException extends RuntimeException{
    private Integer code;
    
    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }
}
2. 定义异常状态码Code(在Code类添加以下代码)
    // 定义异常状态码
    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;
    public static final Integer BUSINESS_ERR = 60002;
3. 模拟异常代码
在这里插入图片描述
    @Override
    public Book getBookById(Integer id) {
        // 将可能出现的异常进行包装,转换成自定义异常
        // 方法1
        if(id == 1){
            throw new BusinessException(Code.BUSINESS_ERR,"请不要使用你的技术挑战我的耐心");
        }

        // 方法2
        try {
            int i = 1 /0;
        }catch (Exception e) {
            throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请重试");
        }

        return bookDao.getById(id);
    }
3. 修改异常处理器(ProjectExceptionAdvice)中的代码
@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(SystemException.class) // 指定处理哪种类型的异常
    public Result doSystemException(SystemException e){
        // 记录日志
        // 发消息给运维
        // 发送邮件给开发人员
        return new Result(e.getCode(),null,e.getMessage());
    }

    @ExceptionHandler(BusinessException.class) // 指定处理哪种类型的异常
    public Result doBusinessException(BusinessException e){
        return new Result(e.getCode(),null,e.getMessage());
    }


    @ExceptionHandler(Exception.class) // 指定处理哪种类型的异常
    public Result doException(){
        // 记录日志
        // 发消息给运维
        // 发送邮件给开发人员
        return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试");
    }
}
4. 测试

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

⑧:放行静态资源

1. 在config包下创建SpringMvcSupport类
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    }
}
2. 将SpringMvcSypport类加入到SpringMvcConfig中
在这里插入图片描述

十三、拦截器

在这里插入图片描述

①:拦截器入门

1. 创建ProjectInterceptor类(定义拦截器)
@Controller
public class ProjectInterceptor implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle~~~~");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle~~~~");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion~~~~");
    }
}
在这里插入图片描述 在这里插入图片描述

|

2. 配置执行哪些请求时进行拦截(在SpringMvcSupport)添加一部分代码
在这里插入图片描述
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {

    @Autowired  // 使用自动装配完成拦截器的注入
    private ProjectInterceptor projectInterceptor;

    // 释放静态资源
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    }

    // 配置拦截对象
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        // 只要请求books这个请求路径是就进行拦截
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
    }
}

②:简化以上开发

1. 直接在SpringMvcConfig类中实现WebMvcConfigurer接口(但有侵入的缺陷)
在这里插入图片描述
@Configuration
@ComponentScan({"com.it.controller","com.it.config"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer{

    @Autowired  // 使用自动装配完成拦截器的注入
    private ProjectInterceptor projectInterceptor;

    // 释放静态资源
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    }

    // 配置拦截对象
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 只要请求books这个请求路径是就进行拦截
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
    }
}

③:拦截器参数

在这里插入图片描述## ④:拦截器链配置

1. 在创建一个拦截器
在这里插入图片描述
@Controller
public class ProjectInterceptor2 implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle~~~~222");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle~~~~222");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion~~~~222");
    }
}

2. 将拦截器2加入到SpringMvcConfig中
在这里插入图片描述
@Configuration
@ComponentScan({"com.it.controller","com.it.config"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer{

    @Autowired  // 使用自动装配完成拦截器的注入
    private ProjectInterceptor projectInterceptor;
    @Autowired
    private ProjectInterceptor2 projectInterceptor2;

    // 释放静态资源
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    }

    // 配置拦截对象
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 只要请求books这个请求路径是就进行拦截
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
        registry.addInterceptor(projectInterceptor2).addPathPatterns("/books", "/books/*");
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

七@归七

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

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

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

打赏作者

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

抵扣说明:

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

余额充值