Spring MVC学习笔记

一、Spring MVC

Spring MVC是由Spring官方提供的基于MVC设计理念的web框架

Spring MVC是基于Servlet封装的用于实现MVC控制的框架,实现前端和服务端的交互

1.1 Spring MVC优势

  • 严格遵守了MVC分层思想
  • 采用松耦合,插件式的结构;更灵活
  • SpringMVC是基于Spring的扩展、提供了一套完善的MVC注解
  • SpringMVC在数据绑定。视图解析都提供了多种处理方式,可灵活配置
  • SpringMVC对RESTful URL设计方法提供了良好的支持

1.2 SpringMVC本质工作

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

二、SpringMVC框架部署

2.1 基于Maven创建一个Web工程

2.2 添加SpringMVC依赖

  • Spring-context
  • Spring-aspects
  • Spring-jdbc
  • Spring-web
  • Spring-webmvc
  • Spring-test
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springmvc-demo1</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>

    <properties>
        <spring.verson>5.2.13.RELEASE</spring.verson>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.verson}</version>
        </dependency>
    </dependencies>
</project>

2.3 创建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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/cache"
       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/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <!--声明使用注解配置-->
    <context:annotation-config/>
    <!--声明Spring工厂注解的扫描范围-->
    <context:component-scan base-package="com"/>
    <!--声明MVC使用注解驱动-->
    <mvc:annotation-driven/>

</beans>

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

SpringMVC提供了一个名为DispatcherServlet的类(SpringMVC的中央处理器,也就是前端控制器),拥有拦截用户请求交由SpringMVC处理

三、SpringMVC框架的使用

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

3.1 创建控制器

  • 创建一个名为com的包(包需要被SpringMVC管理)controllers

  • 创建一个类(无需做任何继承和实现)

  • 在类上添加@Controller声明此类为SpringMVC的控制器

  • 在类上添加@RequestMapping("url")声明此控制器类的请求url

3.1.1 创建控制器类

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

}

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

  • 在一个控制器类中可以定于多个方法处理不同的请求
  • 在每个方法上添加@RequestMapping("url")声明此当前方法请求的url
@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add")
    public void add(){
        System.out.println("bookadd");
    }
    @RequestMapping("/list")
    public void list(){
        System.out.println("booklist");
    }
}

3.1.3 访问

http://localhost:8080/springmvc_demo1/book/add

http://localhost:8080/springmvc_demo1/book/list

3.1.4 /*和/的区别

  • /*拦截所有HTTP请求,包括jsp的请求,都为控制器请求
  • /拦截所有HTTP请求,但不包括jsp的请求,但不会放行静态资源(html,css,js,图片)

3.1.5 静态资源的访问(在spring-servlet.xml)

<!--放行静态资源-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/pages/**" location="/pages/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/images/**" location="/images/"/>

3.2 前端提交数据到服务器

3.2.1 创建前端页面

  • bookadd
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <link rel="stylesheet" href="css/style.css"/>
</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>

3.2.2前端页面提交数据

  • 表单提交:输入框需要提供name属性,SpringMVC控制器是通过name属性取值的
  • 超链接url提交:
  • AJAX提交:请求行、请求头、请求体都可以用来传值。

3.4 控制器接受前端提交的数据

3.4.1 请求行传值

  • 表单提交
  • 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>
  • 控制器接收数据
@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add")
    public void add(@RequestParam("name") String a,
                    @RequestParam("author") String b,
                    @RequestParam("price") double c){
        System.out.println("bookadd");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
    @RequestMapping("/list")
    public void list(){
        System.out.println("booklist");
    }
}

注意如果控制器方法中接收数据的参数名与请求行传值的key的一致,则@RequestParam可以省略

3.4.2 请求头传值

  • ajax封装请求头数据

    $.ajax({})

3.4.3 请求体传值

  • ajax封装请求体数据

**@RequestBody**注解用于接收请求体传递数据

@RequestBody 将前端请求的json数据,转换为java对象,依赖jackson

  • 前端
  <script type="text/javascript">
        $("#btn").click(function (){
            var obj={};
            obj.bookName="java";
            obj.bookAuthor="张三";
            obj.bookPrice=3.3;
      	   var s=JSON.stringify(obj);//将对象转换成JSON格式
            $.ajax(
                url:"book/update",
                type:"post",
                contentType:"application/json",
                //如果data的值为json格式字符串,contentType必须设置为"application/json"
                data:s,
                success:function(res){
                console.log(res);
            }
            );
        });
    </script>
  • 导入jackson的依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>
  • 控制器
@RequestMapping("/update")
public void update(@RequestBody Book book){
    System.out.println("bookupdate");
}

3.5 控制器响应前端请求

3.5.1 控制器响应同步请求

同步请求:from、超链接

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

    • 返回为String类型

    请求跳转(转发)

    @RequestMapping("/add")
    public String add(String bookName,
                      String bookAuthor,
                      double bookPrice){
        System.out.println("bookadd");
        System.out.println(bookName);
        System.out.println(bookAuthor);
        System.out.println(bookPrice);
        return "/tips.jsp";
    }
    

    重定向

    @RequestMapping("/add")
    public String add(String bookName,
                      String bookAuthor,
                      double bookPrice){
        System.out.println("bookadd");
        System.out.println(bookName);
        System.out.println(bookAuthor);
        System.out.println(bookPrice);
        return "redirect:/tips.jsp";
    }
    
    • 返回为ModelAndView

    请求跳转(转发)

    @RequestMapping("/add")
    public ModelAndView add(String bookName,
                      String bookAuthor,
                      double bookPrice){
        System.out.println("bookadd");
        System.out.println(bookName);
        System.out.println(bookAuthor);
        System.out.println(bookPrice);
        ModelAndView modelAndView=new ModelAndView("/tips.jsp");
        return modelAndView;
    }
    

    重定向

    @RequestMapping("/add")
    public ModelAndView add(String bookName,
                      String bookAuthor,
                      double bookPrice){
        System.out.println("bookadd");
        System.out.println(bookName);
        System.out.println(bookAuthor);
        System.out.println(bookPrice);
        ModelAndView modelAndView=new ModelAndView("redirect:/tips.jsp");
        return modelAndView;
    }
    

    3.5.2 控制器响应异步请求

    异步请求:ajax请求

  • 使用response中输出流进行响应

    • 控制器方法的返回类型为void
    • 控制器方法添加HttpServletResponse response参数
    • response.setcharacterEncoding(“utf-8”);
        <script type="text/javascript">
            $("#btn").click(function (){
                var obj={};
                obj.bookName="java";
                obj.bookAuthor="张三";
                obj.bookPrice=3.3;
                $.ajax(
                    url:"book/add",
                    type:"post",
                    dataType:"json",
                    headers:{
    
                    },
                    data:obj,
                    success:function(res){
                    console.log(res);
                }
                );
            });
    
    @RequestMapping("/update")
    public void update(@RequestBody Book book, HttpServletResponse response) throws IOException {
        System.out.println("bookupdate");
        String s=new ObjectMapper().writeValueAsString(book);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json");
        PrintWriter out= response.getWriter();
        out.println(s);
        out.flush();
        out.close();
    }
    

    直接在控制方法的返回类型设置为响应对象

    • 控制器方法的返回类型设置为给ajax请求的对象类型
    • 在控制器方法前添加@ResponseBody注解,将返回的对象转换为json响应给ajax请求
@RequestMapping("/update")
@ResponseBody
public List<Book> update(@RequestBody Book book){
    System.out.println("---bookUpdate");
    List<Book> books=new ArrayList<Book>();
    books.add(new Book(1,"java","老张",2.22));
    books.add(new Book(2,"c++","老李",3.22));
    return books;
}

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

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

  • 返回类型为String
//在控制器方法中定义一个Model类型的参数
//在return页面之前,向model中添加键值对,添加的键值对就会被传递到转发
@RequestMapping("/add")
public String add(String bookName,
                  String bookAuthor,
                  double bookPrice, Model model){
    System.out.println("bookadd");
    System.out.println(bookName);
    System.out.println(bookAuthor);
    System.out.println(bookPrice);
    model.addAttribute("key","value");
    return "/tips.jsp";
}

//除了使用model对象传值外,还可以使用HttpServletRequest
@RequestMapping("/add")
public String add(String bookName,
                  String bookAuthor,
                  double bookPrice, HttpServletRequest request){
    System.out.println("bookadd");
    System.out.println(bookName);
    System.out.println(bookAuthor);
    System.out.println(bookPrice);
    request.setAttribute("key","value");
    return "/tips.jsp";
}
  • 返回类型为ModelAndView
@RequestMapping("/add")
public ModelAndView add(String bookName,
                  String bookAuthor,
                  double bookPrice){
    System.out.println("bookadd");
    System.out.println(bookName);
    System.out.println(bookAuthor);
    System.out.println(bookPrice);
    ModelAndView modelAndView=new ModelAndView("/tips.jsp");
    modelAndView.addObject("key","value");
    return modelAndView;
}

3.6 解决中文乱码问题

3.6.1 前端编码

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

3.6.2 服务器编码

  • tomcat/conf/server.xml
<Connector port="8080" protocol="HTTP/1.0" connectionTimeout="20000" redirectPort="8443" URIEcoding="UTF-8"/>

3.6.3 设置SpringMVC的编码方式

  • 在web.xml中配置SpringMVC编码过滤器的编码方式
<filter>
    <filter-name>EcodingFilter</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>EcodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

四、SpringMVC的请求流程在这里插入图片描述

①前端发送请求被前端控制器DispatcherServlet拦截

②前端控制器调用处理器映射器HandlerMapping对请求URL进行解析,解析之后返回调用给前端控制器

③前端控制器调用处理器适配器处理调用链

④处理器适配器基于反射通过适配器设计模式完成处理器(控制器)的调用处理用户请求

⑤前端控制器调用视图解析器ViewResolveer对ModelAndView进行解析,将解析结果(视图资源和数据)响应给前端控制器

⑥处理器适配器将控制器返回的视图和数据信息封装成ModelAndView响应给前端控制器

⑦前端控制器响应用户请求

4.2 SpringMVC的核心组件

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

4.3 处理器解析器

不同的处理器映射器对URL处理的方式也不相同,使用对应的处理器映射器之后,前端请求规则也要发送相应的变化

  • SpringMVC提供的处理器映射器:
    • BeanNameURLHandlerMapping 根据控制器的ID来访问控制器
    • SimpleURLHandlerMapping 根据控制器配置的URL访问(默认)

配置处理器映射器:

  • 在SpringMVC的配置文件中,通过bean标签声明

  • 配置BeanNameURLHandlerMapping

    <bean class="org.springframework.web.servlet.handler.BeanNameURLHandlerMapping"></bean>
    
  • 配置SimpleURLHandlerMapping

<bean class="org.springframework.web.servlet.handler.SimpleURLHandlerMapping">
	<property name="mappings">
    	<props>
        	<prop key="/a">BookControl</prop>
            <prop key="/b">UserControl</prop>
        </props>
    </property>
</bean>

4.4 视图解析器

Spring提供了多个视图解析器

  • UrlBasedViewResolver
  • InternalResourceViewResolver
  • UrlBasedViewResolver需要依赖jstl
    • 添加jstl依赖
    • 配置视图解析器
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
    <property name="prefix" value="/"/> 
    <property name="suffix" value=".jsp"/>
</bean>
  • InternalResourceViewResolver
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="prefix" value="/"/> 
    <property name="suffix" value=".jsp"/>
</bean>

五、日期格式处理

5.1 在控制器方法中可以使用对象接收

  • 前端
<from action="test/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>
</from>
  • 后端
@Controller
@RequestMapping("/test")
public class testController{
   @RequestMapping("/add")
   //表单提交的多个数据,在控制器方法中可以使用对象接收
   //但是提交的数据的key必须要与对象的属性名一致
   public String addBook(Book book){
       return "/tips.jsp";
   }
}

5.2 日期格式处理

如果前端需要输入日期数据,在控制器中转换Date对象,SpringMVC要求前端输入的日期格式必须

yyyy/MM/dd

如果甲方要求日期格式必须为指定的格式,而这个指定格式SpringMVC不接受

  • 自定义日期转换器

5.2.1 创建自定义日期转换器

public class MyDateConverter implements Converter<String, Date> {

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日");
    public Date convert(String s) {
        Date date = null;
        try {
            date = sdf.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
<!--声明MVC使用注解驱动-->
<mvc:annotation-driven conversion-service="converterFactory"/>
<!--自定义日期类型-->
<bean id="converterFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.utils.MyDateConverter"/>
        </set>
    </property>
</bean>

六、文件上传

6.1 SpringMVC框架部署

  • 基于maven创建Web工程
  • 添加SpringMVC所需依赖
    • spring-context
    • spring-aspects
    • spring-jdbc
    • spring-web
    • spring-mvc
    • jackson
  • 创建SpringMVC配置文件
  • 在web.xml中配置SpringMVC的前端控制器
  • 在web.xml中配置SpringMVC的编码过滤器

6.2 文件上传

案例:添加图书、同时提交图书的封面图片

6.2.1 前端提交的文件

  • 表单提示方式必须为POST
  • 表单enctype属性设置为multipart/from-data
<from action="book/add" method="post" enctype="multipart/from-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>
</from>

6.2.2 控制器接收数据和文件

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.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
  • 配置multipartResolver文件解析器
<!--文件解析器-->
<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类型的对象,就可以接收图片
@RequestMapping("/add1")
public String add(Book book, MultipartFile imgFile, HttpServletRequest request) throws IOException {
    //imgFile表示上传的路径
    //截取上传文件的后缀名,生成新的后缀名
    String oringnalFilename=imgFile.getOriginalFilename();
    String ext=oringnalFilename.substring(oringnalFilename.lastIndexOf("."));
    String fileName=System.currentTimeMillis()+ext;
    //获取imgs目录在服务器的路径
    String dir=request.getServletContext().getRealPath("images");
    String savePath=dir+"/"+fileName;
    imgFile.transferTo(new File(savePath));
    book.setBookName("images/"+fileName);
    //调用service存储到数据库
    return "/tips.jsp";
}

6.3 文件下载

6.3.1 显示文件列表

  • 前端
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
	$.get("book/list",function(res){
        for(var i=0;i<res.length;i++){
            var fn=res[i];
            var htmlstr="<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6"><div class="thumbnail"><img src='"images/"+fn+"' alt='...'><div class="caption"><p><a href="#"class="btn btn-primary" role='button'>下载</a></p></div></div></div>";
            $("#container").append(htmlstr);
        }
    },"json");
</script>
  • BookController
@RequestMapping("/list")
@ResponseBody
public String[] listImgs(HttpServletRequest request){
    //从imgs目录下获取所有的图片信息
    String dir=request.getServletContext().getRealPath("images");
    File imgDir=new File(dir);
    String []fileNames=imgDir.list();
    return fileNames;
}

6.3.2 文件下载

@RequestMapping("/download")
public void downloadImg(String fname,HttpServletRequest request,HttpServletResponse response) throws IOException {
    String dir=request.getServletContext().getRealPath("/images");
    String filePath=dir+"/"+fname;
    FileInputStream fileInputStream=new FileInputStream();
    response.setContentType("application/exe");
    response.addHeader("Content-Disposition","Attachment;fileName="+fname);

    IOUtils.copy(fileInputStream,response.getOutputStream());
}

七、统一异常处理

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

7.1 HTTP状态异常统一处理

HTTP STATUS 404

  • 创建一个用于进行异常提示的页面:404.jsp

  • 在web.xml中配置

<error-page>
    <error-code>404</error-code>
    <location>/404.jsp</location>
</error-page>

7.2 java代码异常的统一处理

  • 创建error.jsp
  • 在web.xml中进行配置
<error-page>
    <exception-type>java.lang.NumberFormatException</exception-type>
    <location>/error.jsp</location>
</error-page>

7.3 SpringMVC异常处理

MyExceptionHandler

package com.utils;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    public String nullHandler(){
            return "/error.jsp";
    }
    @ExceptionHandler(NumberFormatException.class)
    public String FormatHandler(){
        return "/error.jsp";
    }
}

八、拦截器

8.1 拦截器介绍

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

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

8.2 自定义拦截器

<!--拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/book/query"/>
        <bean class="com.utils.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>

8.3 拦截器链

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

九、SSM整合

9.1 创建web项目

  • 创建maven工程
  • 修改pom文件packing=war
<packaging>war</packaging>
  • 完成maven工程web项目结构

  • 添加web项目依赖:

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
  • 配置服务器运行环境

9.2 部署Mybatis

  • 添加Mybatis依赖

    <!--mysql-->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
        <scope>provided</scope>
    </dependency>
    
  • 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">

<!-- MyBatis的全局配置文件 -->
<configuration>
  
</configuration>

9.3 部署Spring、SpringMVC

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SSM-demo1</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>
    <properties>
        <spring.verson>5.2.13.RELEASE</spring.verson>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/jsp-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </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>
        <!--mysql-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--spring-context-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--aspects-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--test-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--web-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--webmvc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.verson}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <!--jackson-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.2.2</version>
        </dependency>
    </dependencies>
</project>
  • 创建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/>
        <!--声明Spring工厂注解的扫描范围-->
        <context:component-scan base-package="com.dao"/>
    
    
    </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:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/cache"
           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/cache http://www.springframework.org/schema/cache/spring-cache.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: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">
       
    
    
    </beans>
    

9.3.3 配置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-*.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>

9.4 整合配置

9.4.1 导入spring-mybatis依赖

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.7</version>
</dependency>

9.4.2 配置druid

  • 添加druid依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/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/tb_student?characterEncoding=utf-8
druid.username=root
druid.password=

druid.pool.init=1
druid.pool.minIdle=3
druld.pool.maxActive=20
druid.pool.timeout=30000
  • 在spring-mybatis.xml配置数据源
<context:property-placeholder location="classpath:druid.properties"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driver" 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="${druld.pool.maxActive}"/>
    <property name="maxWait" value="${druid.pool.timeout}"/>
</bean>

9.4.3 配置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.bean"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <property name="basePackage" value="com.dao"/>
</bean>

9.5 整合配置(AOP)

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

基于注解的事务管理配置

  • 将Spring提交的事务管理切面类配置到Spring容器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

9.6 整合测试

9.6.1 完成user的查询

  • 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private int userId;
    private String userName;
    private String userRealName;
    private String userImg;
}
  • 在DAO包中创建接口
public interface UserDAO {
    public User queryUserNameByName(String name);
} 
  • 导入junit包
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值