Spring MVC框架

Spring MVC框架

一、Spring MVC概述

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

Spring MVC优势

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

Spring MVC本质工作

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

三、Spring MVC框架部署

3.1 基于maven创建一个web工程

3.2 添加SpringMVC依赖

 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring-version>5.2.12.RELEASE</spring-version>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>

    </dependencies>

3.3 创建MVC配置文件

  • 在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:aop="http://www.springframework.org/schema/aop"
       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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    <context:annotation-config/>
    <context:component-scan base-package="com.zhang"/>
    <!--    声明MVC采用注解驱动-->
    <mvc:annotation-driven/>
</beans>

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

SpringMVC提供了一名为DispatcherServlet的类(SpringMVC的前端控制器),用于拦截用户请求交由SpringMVC处理。
具体是在web.xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">    
    <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>
</web-app>

三、SpringMVC框架使用

在SpringMVC中,

3.1 创建控制器

3.1.1 创建控制器类

  • 创建名为com.zhang.controllers的包,这个包必须在Spring注解扫描的范围内。
  • 创建一个类(无需做任何的继承和实现)。
  • 在类上添加注解@Controllers,声明此类为SpringMVC的控制器。
  • 在类上添加@ RequestMapping(“url”),声明此控制器类的请求url。
@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("---------book add");
    }
    @RequestMapping("/list")
    public void list(){
        System.out.println("---------book list");

    }

3.1.3 访问

http://localhost:8080/spring_mvc_demo/book/add
http://localhost:8080/spring_mvc_demo/book/list
在这里插入图片描述

3.2 静态资源配置

静态资源:就是项目中的HTML,css,js,图片,字体等。

3.2.1 /*和/的区别

3.2.2 静态资源放行配置

  • 在SpringMVC的配置文件,添加如下静态资源放行的配置
    <!--    配置静态资源放行-->
    <mvc:resources mapping="/css/" location="/css/"/>
    <mvc:resources mapping="/pages/" location="/pages/"/>
    <mvc:resources mapping="/img/" location="/img/"/>

3.3 前端提交数据到控制器

3.3.1 创建前端页面

  • book-add.jsp 表单的action属性设置为控制器类的url和对应方法的url的组合路径。

3.3.2 前端页面提交数据

  • 表单提交:输入框需要提供name属性,SrpingMVC控制器是通过name属性取值的。
<head>
    <title>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>
  • URL提交:
<a href="book/add?bookName=java"/>
  • AJAX提交:请求行,请求头,请求体都可以用来传值。
<h3>AJAX提交</h3>
    <input type="button" value="ajax提交">
    <script type="text/javascript" src="js/jQuery-3.6.js"></script>
    <script type="text/javascript">
        $("#bt1").click(function (){
            var obj = {};
            obj.bookName="java";
            obj.bookAuthor="张三";
            obj.bookPrice=3.33;

            $.ajax({
                url:"book/add",
                type:"post",
                header:{

                },
                contentType:"application/json",
                data:obj,
                success:function (res){
                    console.log(res);
                }
            })
        })
    </script>

3.4 控制器接收前端请求

3.4.1 请求行传值

  • 表单提交
  • URL提交
  • $.ajax()请示的url传值
  • . p o r t ( ) / .port()/ .port()/.get()中的{}传值
    @RepuestParam注解用于接收请求行传递的数据
  • 前端提交数据
<form action ="/spring_mvc_demo/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 a,
                    @RequestParam("bookAuthor") String b,
                    @RequestParam("bookPrice") Double c){
        System.out.println("---------book add");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }

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

    @RequestMapping("/add")
    public void add(String bookName,
                    String bookAuthor,
                    Double bookPrice){
        System.out.println("---------book add");
        System.out.println(bookName);
        System.out.println(bookAuthor);
        System.out.println(bookPrice);
    }

3.4.2 请求头传值

  • ajax封装请求体数据
$.ajax({
	...,
	headers:{
	},
	...
})

@RequestHeader注解用于接收请求行头传递的数据

  • 前端
<input type="button" value="ajax提交" id="btn1">
<script type="text/javascript" src="js/jQuery-3.6.js"></script>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName="java";
        obj.bookAuthor="张三";
        obj.bookPrice=3.33;

        $.ajax({
            url:"/spring_mvc_demo/book/list",
            type:"post",
            headers:{
                token:"zhanghengchao"
            },
            // contentType:"application/json",
            // data:obj,
            success:function (res){
                console.log(res);
            }
        })
    })
</script>
  • 控制器
    @RequestMapping("/list")
    public void list(@RequestHeader("token") String token) {
        System.out.println("---------book list");
    }

3.4.3 请求体传值

  • ajax封装请求体数据
	$.ajax({
		...
		contentType:"application/josn",
		data:obj,,
		...
		})

@RequestBody注解用于接收请求行头传送的数据

  • 前端
<input type="button" value="ajax提交" id="btn1">
<script type="text/javascript" src="js/jQuery-3.6.js"></script>
<script type="text/javascript">
    $("#btn1").click(function (){
        var obj = {};
        obj.bookName="Python";
        obj.bookAuthor="明明";
        obj.bookPrice=3.33;

        var s = JSON.stringify(obj);  // 将对象转换为json格式
        $.ajax({
            url:"/spring_mvc_demo/book/update",
            type:"post",
            contentType:"application/json;charset=UTF-8",
            data:s, //如果data的值为json格式字符串,contentType必须设置为application/json
            success:function (res){
                console.log(res);
            }
        })
    })
</script>

@RequrestBody将前端请求提交的JSON格式数据转换成java对象,依赖jackson

  • pom依赖中添加jackson依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.4</version>
        </dependency>
  • 控制器
    @RequestMapping("/update")
    public void update(@RequestBody Book book) {
        System.out.println("---------book update");
        System.out.println(book);
    }

3.5 控制器响应前端请求

3.5.1

同步请求 form 超链接

  • 处理同步请求方法的返回类型为String或者ModelAndView,以实现页面的跳转
    • 返回类型为String
      转发
    @RequestMapping("/add")
    public String add(String bookName,
                    String bookAuthor,
                    Double bookPrice
                                    ){
        System.out.println("---------book add");
        //如何跳转到指定的页面
        return "/tips.jsp";   
    }

重定向

    @RequestMapping("/add")
    public String add(String bookName,
                    String bookAuthor,
                    Double bookPrice
                                    ){
        System.out.println("---------book add");
        //如何跳转到指定的页面
        return "redirect:/tips.jsp";   
    }

– 返回值为ModelAndView
转发

    @RequestMapping("/add")
    public ModelAndView add(String bookName,
                            String bookAuthor,
                            Double bookPrice
                                    ){
        System.out.println("---------book add");
        //如何跳转到指定的页面
        ModelAndView modelAndView = new ModelAndView("/tips.jsp");
        return modelAndView;
    }

重定向

    @RequestMapping("/add")
    public ModelAndView add(String bookName,
                            String bookAuthor,
                            Double bookPrice
                                    ){
        System.out.println("---------book add");
        //如何跳转到指定的页面
        ModelAndView modelAndView = new ModelAndView("redirect:/tips.jsp");
        return modelAndView;
    }

3.5.2 控制器响应异步请求

异常请求: ajax请求,非常重要,所有的前后端分离项目,都是ajax请求。

  • 使用response中的输出流进行响应。
    – 控制器方法的返回类型必须为void。
    – 必须要给出response对象。HttpServletResponse response
    – 在方法中通过response
@RequestMapping("/update")
    public void update(@RequestBody Book book, HttpServletResponse response) throws IOException {
        System.out.println("---------book update");
        System.out.println(book);

        //使用ObjectMapping将对象转换为JSON格式字符串
        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请求。
    – 如果一个类中所有方法都是响应ajax请求,只需要在类头上添加@ResponseBody注解即可。
	@RequestMapping("/update")
    @ResponseBody
    public List<Book> update() throws IOException {
        System.out.println("---------book update");
        List<Book> books = new ArrayList<>();
        books.add(new Book(1,"java","李军",2.99));
        books.add(new Book(2,"C++","李何",2.99));
        return books;
    }

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

对于同步请求的转发响应,我们可以传递参数到转发的页面
– 返回值类型为String

// 1.在控制器方法中定义一个Model类型的参数
// 2.在return页面之前,向model中添加键值对,添加的键值对就会被传递到转发的页面。
 @RequestMapping("/add")
    public String add(String bookName,
                            String bookAuthor,
                            Double bookPrice,
                            Model model
                                    ){
        System.out.println("---------book add");

        model.addAttribute("key1","value1");
        model.addAttribute("book",new Book(1,"java","李军",2.99));
        return "/tips.jsp";
    }
// 除了使用Model对象传值外,还可以直接使用HttpServletRequest对象传值
 @RequestMapping("/add")
    public String add(String bookName,
                            String bookAuthor,
                            Double bookPrice,
                            HttpServletRequest request
                                    ){
        System.out.println("---------book add");

        request.setAttribute("key1","value1");
        request.setAttribute("book",new Book(1,"java","李军",2.99));
        return "/tips.jsp";
    }

– 返回ModeAndView

    @RequestMapping("/add1")
    public ModelAndView add1(String bookName,
                            String bookAuthor,
                            Double bookPrice
                                    ){
        System.out.println("---------book add");

        //如何跳转到指定的页面
        ModelAndView modelAndView = new ModelAndView("/tips.jsp");
        modelAndView.addObject("key1","value1");
        modelAndView.addObject("book",new Book(1, "java", "李军", 2.99))
        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 大约在68行
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8"/>

3.6.3 设置SpringMVC的编码方式

通过参数的形式将SpringMVC的编码方式

  • 在web.xml中配置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>

四、SpringMVC的请求处理流程

4.1 请求处理流程

SrpingMVC通过前端控制器
拦截并处理用户请求
在这里插入图片描述

1)前端发送请求被前端控制器DispathcerServlet拦截。
2)前端控制器调用处理器映射器HandlerMapping对请求URL进行解析,解析之后返回调用链给前端控制器。
3)前端控制器调用处理器适配器处理调用链。
4)处理器适配器基于反射通过适配器设计模式完成处理器(控制器)的调用处理用户请求。
5)处理器适配器将控制器返回的视图和数据信息封装成ModelAndView响应给前端控制器。
6)前端控制器调用视图解析器ViewResolver对ModelAndView进行解析,将解析结果(视图资源和数据)响应给前端控制器。
7)前端控制器调用视图View组件将数据进行渲染,将渲染结果(静态视图)响应给前端控制器,
8)前端控制器响应用户请求。

4.2 SpringMVC核心组件

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

4.3 处理器映射器

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

  • BeanNameUrlHanlerMapping 根据控制器的ID访问控制器
  • SimpleUrlHandlerMapping 根据控制器配置的URL访问(默认)
    配置处理器映射器
  • 在SpringMVC的配置文件中通过bean配置BeanNameUrlHandlerMapping
    <!-- HandlerMapping BeanNameUrlHandlerMapping-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>

配置之后,即可以省略@RequestMapping注解,而使用小写字母开头的类名称实现映射

  • SimpleUrlHandlerMapping
    <!--    -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props key="/aaa">bookController</props>
            <props key="/bbb">studentController</props>
        </property>
    </bean>

有了props 的配置项,也可以省略在控制类前的@RequestMapping映射。

4.4 视图解析器

SpringMVC提供了多个视图解析器

  • UrlBaseViewResolver
    – pom中添加JSTL的依赖
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

– 配置视图解析器

    <bean 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 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value"/"/>
        <property name="suffix" value"jsp"/>
    </bean>

五、日期格式处理

5.1在控制器中使用对象接收数据

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

5.2 日期格式处理

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

  • 自定义日期转换器

5.2.1 创建自定义日期转换器

/***
 *  1.创建一个类实现Converter接口,泛型指定从什么类型转换为什么类型
 *  2.实现convert 方法
*/

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;
    }
}

5.2.1 配置自定义日期转换器

放在转换器工厂,再配置给SpringMVC

    <!--    声明MVC采用注解驱动 -->
    <mvc:annotation-driven conversion-service="converterFactory"/> 
    <bean id="converterFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.zhang.utils.MyDateConverter"/>
            </set>
        </property>
    </bean>

六、文件上传

6.1 SpringMVC框架部署回顾

  • 基于maven创建web工程

  • 添加依赖

    • Springcontext aspects jdbc web webmvc jackson
  • 创建 SpringMVC配置文件

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

  • 在web.xml中配置SpringMVC的编码过滤器
    pom中添加war
    src-main下创建webapp
    webapp下创建WEB-INF
    WEB-INF下创建web.xml
    Project Structure中设置
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    按模板创建 spring-servlet-xml 并配置好
    按模板创建werb.xml 并配置好

  • 配置springMVC静态资源处理策略

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

6.2 文件上传

案例说明:添加图书,同时提交图书的封面图片。

6.2.1 前端提交文件

  • 表单提交方式必须为post
  • 表单enctype=“multipart/form-data”
    <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" name="提交"></p>
    </form>

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.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • 在Spring-servlet.xml 中配置文件解析器
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10240000"></property>
        <property name="maxInMemorySize" value="102400"></property>
        <property name="defaultEncoding" value="utf-8"></property> 
    </bean>
  • 控制器接收文件
    – 在处理文件上传的方法中定义一个MultiPartFile的对象

6.3 文件下载

6.3.1 文件列表显示

  • list.jsp
<%--
  Created by IntelliJ IDEA.
  User: zhanghc
  Date: 2021/10/30
  Time: 20:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=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>

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

<script type="text/javascript" src="js/jQuery-3.6.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='imgs/"+fn+"' alt='...'><div class='caption'><p><a href='#' class='btn btn-primary' role='button'>下载</a></p></div></div></div>"
            $("#container").append(htmlStr);
        }
        console.log(res)
    },"json");

</script>
</body>
</html>

  • BookController
    @RequestMapping("/list")
    @ResponseBody
    public String[] listImgs(HttpServletRequest request){
        // 1.从imgs目录下获取所有图片信息
        String dir = request.getServletContext().getRealPath("imgs");
        File imgDir = new File(dir);
        String[] fileNames = imgDir.list();
        return fileNames;
    }

6.3.2 文件下载

  • list.jsp
var htmlStr = "<div class='col-lg-2 col-md-3 col-sm-4 col-xs-6'><div class='thumbnail'><img src='imgs/"+fn+"' alt='...'><div class='caption'><p><a href='book/download?fname="+fn+"' class='btn btn-primary' role='button'>下载</a></p></div></div></div>"
  • BookController
    @RequestMapping("/download")
    public void downloading(String fname, HttpServletRequest request, HttpServletResponse response) throws Exception {

        // 从imgs目录中找到当前文件
        String dir = request.getServletContext().getRealPath("imgs");
        String filePath = dir+"/"+fname;
        FileInputStream fileInputStream = new FileInputStream(filePath);

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

七、统一异常处理

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

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代码异常的统一处理

7.2.1 基于servlet-api处理

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

7.2.2 基于SpringMVC处理

  • 添加异常处理类 在包utils下创建MyExceptionHandler异常处理类,类中添加注解@ControllerAdvice,类中方法添加@ExceptionHandler
@ControllerAdvice
public class MyExceptionHandler {
    @ExceptionHandler(NullPointerException.class)
    public String nullHandler(){
        return "/err.jsp";

    }
     @ExceptionHandler(NumberFormatException.class)
    public String numberHandler(){
          return "/err.jsp";
    }
}

八、拦截器

8.1 什么是拦截器

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

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

8.2

  • 创建拦截器类,在utils下创建
public class MyInterceptor1 implements HandlerInterceptor {
    
    //预处理方法
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("-------------------预处理");
        Enumeration<String> keys = request.getParameterNames();
        while(keys.hasMoreElements()){
            String key = keys.nextElement();
            if("bookId".equals(key)) {
                return true;
            }
        }
        response.setStatus(400);
        return false;
    }
    
    // 后处理方法
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        modelAndView.addObject("tips","这是通过拦截器的后处理添加的数据");
        System.out.println("-------------------后处理");
    }
}
  • 配置拦截器,在SpringMVC中配置拦截路径,拦截器类
    <mvc:mapping path="/student/**"/>
    <mvc:exclude-mapping path="/student/add"/>
    表示拦截student下所有控制器,但排查add下的控制器
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/book/query"/>
            <mvc:mapping path="/student/**"/>
            <mvc:exclude-mapping path="/student/add"/>
            <bean class="com.zhang.utils.MyInterceptor1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

8.3 拦截器链

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

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/book/query"/>
            <bean class="com.zhang.utils.MyInterceptor1"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/book/query"/>
            <bean class="com.zhang.utils.MyInterceptor2"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

对应的执行链顺序如下。
在这里插入图片描述

九、SSM整合

9.1 创建web项目

基于maven完成

  • 创建maven web项目
  • pom文件中packing
<packaging>war</packaging>
  • 完善maven工程的web项目结构
  • pom中添加web项目依赖
<!-- 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>3.1.0</version>
            <scope>provided</scope>
        </dependency>
  • 配置服务器运行环境
    在这里插入图片描述
    在这里插入图片描述

9.2 部署Mybatis

  • 添加Mybatis依赖
        <!-- mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</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.20</version>
            <scope>provided</scope>
        </dependency>
  • 创建Mybatis配置文件mybatis-config.xml

9.3 部署Spring,SpringMVC

9.3.1 添加依赖

context,aptects,jdbc,test,web,webmvc,jackson

 	<properties>
        <maven.compiler.source>3.8.2</maven.compiler.source>
        <maven.compiler.target>3.8.2</maven.compiler.target>
        <spring-version>5.2.12.RELEASE</spring-version>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>        
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.4</version>
        </dependency>

9.3.2 创建spring配置文件,多配置文件分开配置的方式。

– spring-context.xml 只配置注解声明,以及类的配置

– spring-mvc.xml 进行mvc相关的配置,静态资源,拦截器

– spring-mybatis.xml 进行spring与mybaits整合相关的配置

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

9.4 整合配置

9.4.1 导入mybatis-spring依赖

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

9.4.2 配置druid连接池

  • 添加druid依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

  • 创建druid.properties属性文件,并配置
druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf-8
druid.username=root
druid.password=root

## 连接池参数
druid.pool.initSize=1
druid.pool.minIdle=3
druid.pool.maxActive=20
druid.pool.timeout=30000

注意:因The server time zone value****报错,加了“?serverTimezone=UTC&”

  • 在spring-mybatis.xml配置数据源
   <context:property-placeholder location="classpath:druid.properties" />
    <!-- 依赖spring容器完成数据源datasource的创建-->
    <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="1" />
        <property name="minIdle" value="3" />
        <property name="maxActive" value="20" />
        <property name="maxWait" value="30000" />
    </bean>

9.4.3 配置SqlSessionFactory

  • 在spring-mybatis.xml配置SqlSessionFactory
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="druidDataSource"/>
        <property name="mapperLocations" value="classpath:mappers/*.xml"/>
        <property name="typeAliasesPackage" value="com.zhang.bean"/>
        <property name="configLocation" value="classpath*:mybatis-config.xml"/>
    </bean>

9.4.4 配置MapperScannerConfigurer

  • 在spring-mybatis.xml配置MapperScannerConfigurer
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.zhang.dao"/>
    </bean>

9.5 整合配置AOP

使用spring 提供的事务管理完成DAO操作的事务管理
一般采用基于注解的方式

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

tx:annotation-driven需要在文件中加入命名空间引用

    xmlns:tx="http://www.springframework.org/schema/tx" 
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

9.6 整合测试

9.6.1 完成User的查询操作

  • 创建实体类bean/User.java创建
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private int id;
    private String name;
    private String pwd;
}
  • 创建接口 dao/UserDAO
public interface UserDAO {
    public User queryUserByName(String name);
}
  • 在mappers/UserMapper.xml
<?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.zhang.dao.UserDAO">
        <resultMap id="userMap" type="User">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="pwd" property="pwd"/> 
        </resultMap>

        <select id="queryUserByName" resultMap="userMap">
            select id,name,pwd from user where name=#{name}
        </select>
</mapper>

9.6.2 对DAO进行单元测试

  • 导入junit,spring-test依赖
<!-- https://mvnrepository.com/artifact/junit/junit -->
<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 {

    @Resource
    private UserDAO userDAO;

    @org.junit.Test
    public void queryUserByName() {
        User user = userDAO.queryUserByName("张恒超");
        System.out.println(user);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值