springMVC


一、springMVC 4.2.4 架构图:

在这里插入图片描述

1、运行流程 :

1、用户向服务器发送请求,请求被Spring 前端控制dispatcherServlet捕获。(dispatcherServlet#dodispatch)

2、前端控制器dispatcherServlet将请求交给处理器映射HandlerMapping,处理器映射依据URL进行决策,选择合适的处理器(即controller的方法)。(dispatcherServlet#getHandler)

3、将处理器 和 拦截器数组 及拦截器索引 组成一个处理器执行链返回前端控制器。

4、前端控制根据处理器找到合适的适配器 (HandlerAdapter就是执行处理器的对象)。(dispatcherServlet#getHandlerAdapter)

​ 此时将开始执行拦截器的 preHandler(…)方法【安装配置顺序正向执行】 (mappedHandler.applyPreHandle)

5、使用HandlerAdapter执行控制层处理器方法

提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring

将帮你做一些额外的工作:

a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中  

6、Handler执行完成后,向dispatcherServlet 返回一个ModelAndView对象。

7、此时将开始执行拦截器的 postHandle(…)方法【安装配置逆序执行】(mappedHandler.applyPostHandle)

8、根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据逻辑视图转发和重定向 以及配置的视图解析器 选择合适视图解析器。

9、据Model和View,来渲染视图(dispatcherServlet#render)。

10、渲染视图完毕执行拦截器的 afterCompletion(…)方法【逆向】。 (mappedHandler.triggerAfterCompletion)

11、将渲染结果返回给客户端

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_4_0.xsd"
         version="4.0">

    <!--过滤器按照编写顺序执行,编码过滤器必须放在最前面-->
    <!--配置全局乱码过滤器,解决post和get乱码-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param><!--初始化参数:即构造参数或者属性set设置-->
            <!--设置request请求接收参数编码-->
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <!--设置请求和响应都设置为UTF-8-->
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--设置restFul风格PUT/delete等请求方式过滤器-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <servlet>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.dispatcherServlet</servlet-class>
        <init-param>
            <!--上下文加载springMVC配置文件路径-->
            <!--classpath:指src/main/java 或 resource路径;具体可查看target/项目/WEB-INFO/classes目录-->
            <!-- 使用classpath:表示从类路径查找配置文件,例如maven工程中的 src/main/resources -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <!-- 将启动控制dispatcherServlet的初始化时间提前到服务器启动时-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <!--设置springMVC的核心控制器所能处理的请求的请求路径,
            /所匹配的请求可以是/login或.html或.js或.css方式的请求路径,但是/不能匹配.jsp请求路径的请求
            因为jsp请求需要tomcat处理(/*可匹配)-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

        <!-- 由于springMVC IOC容器依赖注入需要spring IOC 容器,并且由于设置了服务一启动
        dispatcherServlet就初始化。一初始化就是启动springMVC IOC容器,并且spring IOC容器需要
        设置spring容器为parent(调用dispatcherServlet#initWebApplicationContext就初始化SpringMVC容器),
        所以使用ServletContext监听器监听dispatcherServlet初始化之前必须启动spring容器。

        作用:初始化spring容器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--Spring配置文件认位置和名称:/WEB-INF/applicationContext.xml
        可通过上下文参数自定义Spring配置文件的位置和名称-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
    </context-param>

</web-app>

1、url-pattern标签中使用/和/*的区别:

  • / 所匹配的请求可以是 /login 或 .html 或 .js 或 .css 方式的请求路径,但是/不能匹配.jsp请求路径的请求,因此就可以避免在访问jsp页面时,该请求被dispatcherServlet处理,从而找不到相应的页面

  • /* 则能够匹配所有请求,例如在使用过滤器时,若需要对所有请求进行过滤,就需要使用 /* 的写法

2、监听器 过滤器 和 servlet 执行顺序

监听器 – > 过滤器 – > servlet

3、classpath:路径

指src/main/java 或 src/main/resources 路径;具体可查看target/项目/WEB-INFO/classes目录

image-20220821231143692

三、springmvc.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"
       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/mvc
         https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="xiao"/>
    <!--开启注解驱动:处理ajax请求/视图控制直接跳转/json数据/静态资源-->
    <mvc:annotation-driven/>
    <!--视图控制器,当前路径直接跳转页面不经过控制层-->
    <mvc:view-controller path="/" view-name="index"/>

    <!--设置认servlet(因为tomcat容器配置了)处理静态资源,例如html、js、css、jpg
    若只设置该标签,则只能访问静态资源,其他请求则无法访问此时必须设置<mvc:annotation-driven/>解决问题-->
    <mvc:default-servlet-handler/>
    <!-- 开启mvc注解驱动 -->
<!--    <mvc:annotation-driven>
        <mvc:message-converters>
            &lt;!&ndash; 处理响应中文内容乱码 &ndash;&gt;
            <bean
                    class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="defaultCharset" value="UTF-8" />
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html</value>
                        <value>application/json</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>-->

    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver"
          class="org.thymeleaf.Spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <!--输出的编码为 UTF-8-->
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.Spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean
                            class="org.thymeleaf.Spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <!--必须通过文件解析器的解析才能将文件转换multipartfile对象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    </bean>

    <!--拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="xiao.intercept.FirstIntercept"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

四、controller控制器

1、域对象有request、session、ServletContext ,这些都可以传输数据。

2、由于dispatherServlet底层就是servlet,所以依然传输数据时HttpServletReques、 HttpServletResponse,当然可以从request中获取到session和ServletContext 对象。

3、controller类中的方法接收参数类型,HttpServletRequest 、HttpServletResponse、 HttpSession、Model/ModelMap
ModelMap是Model接口的实现类使用效果一样,都会封装成ModelAndView。

4、Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的

5、控制器方法可以自动绑定参数到 实体类、数组。

1、 使用注解@controller

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import xiao.entity.Person;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class HelloController {

    @RequestMapping("/")
    public String index(HttpServletRequest request){
        HttpSession session = request.getSession();
        return "index";
    }

    @RequestMapping("/hello")
    public String hello(Model model){
//org.springframework.validation.support.BindingAwareModelMap
        System.out.println(model.getClass().getName());
        return "success";
    }

    //ant 风格匹配  ?:表示任意的单个字符 *:表示任意的0个或多个字符 **:表示任意层数的任意目录
    @RequestMapping("/hello?")
    public String helloAnt(){
        return "success";
    }

    @GetMapping("/demo/path/{pathValue}")
    public String pathVa(@PathVariable String pathValue){
        System.out.println("路径参数 pathValue = " + pathValue);
        return "success";
    }

    @GetMapping("/demo/param")
    public String param(@RequestParam String param ,
        @RequestHeader(value = "Referer",required = false) String referer,//获取请求头
        @CookieValue("JSESSIONID") String jsessionId){//获取cookie
        System.out.println("简单参数绑定 param = " + param);
        System.out.println("请求头 referer = " + referer);
        System.out.println("请求头cookie jsessionId = " + jsessionId);
        return "success";
    }

    @PostMapping("/demo/entity")
    public String entity(Person person){
        System.out.println("实体类 entity 参数绑定 person = " + person);
        return "success";
    }
}

2、json交互

1、导入jackson的依赖

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>

2、SpringMVC的配置文件中设置开启mvc的注解驱动

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

3、在控制器方法的形参位置,设置json格式的请求参数要转换成的java类型(实体类或map)的参
数,并使用@RequestBody注解标识

①RequestBody     
绑定在方法上,用于接收HTTP请求的json、xml格式数据通过springMVC的HttpMessageConverter转换成java对象。

②ResponseBody     
将数据转换成json,反馈给客户端

// 商品修改提交json信息,响应json信息
	@RequestMapping("/editItemSubmit_RequestJson")
	public @ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {
		System.out.println(items);
		return items;
	}

五、视图

  • SpringMVC视图的种类很多,认有转发视图和重定向视图
  • 当工程引入jstl 的依赖,转发视图会自动转换为 JstlView
  • 若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView

1、 ThymeleafView

    @RequestMapping("/")
    public String index(HttpServletRequest request){
        HttpSession session = request.getSession();
        return "index";
    }

指定逻辑视图名,经过视图解析器解析为html物理路径:/WEB-INF/index.html

2、 重定向视图 RedirectView

return “redirect:/hello”; //重定向到 /hello请求中,相当于response.sendRedirect()。地址发生变化,由客户端发起。产生了一对新request、response,之前的request数据丢失。

    @GetMapping("/redirect")
    public String testRedirectView(RedirectAttributes redirectModel){
        //重定向将参数以路径拼接方式发送 /redirect?redirectValue2=重定向数据保存了
        redirectModel.addAttribute("redirectValue2","重定向数据保存了==2");
        //重定向将参数隐藏发送
        redirectModel.addFlashAttribute("redirectValue3","重定向数据保存了==3");
        //重定向视图
        return "redirect:/hello";
    }

    @RequestMapping("/hello")
    public String hello(Model model,HttpServletRequest request){
	//org.springframework.validation.support.BindingAwareModelMap
        System.out.println(model.getClass().getName());
        System.out.println(request.getParameterMap());
        //model接收addFlashAttribute从定向参数,request接收addAttribute参数
        System.out.println("redirectValue3= " + model.containsAttribute("redirectValue3"));
        return "success";
    }

3、 转发视图 InternalResourceView

SpringMVC中认的转发视图是InternalResourceView

转发,同一个request,并且请求的地址不变还是/forward

    @GetMapping("/forward")
    public String testForwardView(){
        //转发视图
        return "forward:/hello";
    }

4、处理jsp页面转发视图 和 渲染视图 需要 InternalResourceView

由于springMVC.xml中配置了ThymeleafViewResolver 视图解析器,所以认的视图就是 Thymeleaf 视图。

如果想要使用 jsp,就需使用 InternalResourceViewResolver 解析器。

六、文件上传和下载

文件上传和下载都是文件复制的过程,都是通过IO流将数据传输。

1、文件下载

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

    @GetMapping("downImg/{imgName}")//下载文件
    public ResponseEntity<byte[]> downImg(@PathVariable String imgName,
                                          HttpSession session) throws IOException {
        //获取应用上下文
        ServletContext context = session.getServletContext();
        String realPath = context.getRealPath("/img") + File.separator + imgName + ".png";
        InputStream inputStream = new FileInputStream(realPath);
        //available() 获取文件字节长度
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        //创建HttpHeaders对象设置响应头信息
        MultiValueMap<String, String> headers = new HttpHeaders();
        headers.add("Content-disposition", "attachment;filename=" + imgName + ".png");
        return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
    }

2、文件上传

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency

②在SpringMVC的配置文件添加配置:

<!--必须通过文件解析器的解析才能将文件转换multipartfile对象-->
<bean id="multipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
<form th:action="@{/restFul01/uploadFile}" th:method="post" enctype="multipart/form-data">
    文件<input  th:type="file" name="multipartfile">
    <input th:type="submit" th:value="文件上传">
</form>

控制层 multipartfile参数必须和前端的 file的value一致,文件上传要求form表单的请求方式必须为post,并且添加属性enctype=“multipart/form-data”

    @PostMapping("/uploadFile")//文件上传
    public String uploadFile(multipartfile multipartfile,HttpSession session) throws IOException {
        String filename = multipartfile.getoriginalFilename();
        String fileType = filename.substring(filename.lastIndexOf("."));
        ServletContext context = session.getServletContext();
        String realPath = context.getRealPath("upload");
        File file = new File(realPath);
        if(!file.exists()){
            file.mkdir();
        }
        String filePath = realPath + File.separator + filename;
        multipartfile.transferTo(new File(filePath));
        return "success";
    }

七、拦截

1、SpringMVC中的拦截器需要实现handlerinterceptor

Public class handlerinterceptor1 implements handlerinterceptor{

	/**
	 * controller方法执行前调用方法
	 * 返回true表示继续执行,返回false中止执行
	 * 这里可以加入登录校验、权限拦截等(校验用户是否有访问内容的权限)
	 */
	@Override
	Public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		// Todo Auto-generated method stub
		Return false;
	}
	/**
	 * controller方法执行后但未返回视图前调用方法
	 * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
	 */
	@Override
	Public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// Todo Auto-generated method stub
		
	}
	/** controller方法执行后且视图渲染视图后调用方法
	 * 这里可得到执行controller时的异常信息
	 * 这里可记录操作日志,资源清理等
	 */
	@Override
	Public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// Todo Auto-generated method stub		
	}
}

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

<!--拦截器 -->
<mvc:interceptors>
	<!--多个拦截器,顺序执行 -->
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="cn.zixue.springmvc.filter.handlerinterceptor1"></bean>
	</mvc:interceptor>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="cn.zixue.springmvc.filter.handlerinterceptor2"></bean>
	</mvc:interceptor>
</mvc:interceptors>

运行流程(按顺序执行,如果前面中false,后面无法执行)

handlerinterceptor1..preHandle..
handlerinterceptor2..preHandle..

handlerinterceptor2..postHandle..
handlerinterceptor1..postHandle..

handlerinterceptor2..afterCompletion..
handlerinterceptor1..afterCompletion..

2、拦截器 与 过滤器 的区别

浏览器 --> 过滤器 -->前端控制器dispatcherServlet --> 拦截器 --> controller的方法 --> 拦截

filter过滤器用于资源拦截

SpringMVC中的拦截器用于拦截控制器方法的执行

八、异常处理器

1、基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver (认) 和 SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
    <props>
    <!--
    properties的键表示处理器方法执行过程中出现的异常
    properties的值表示若出现指定异常时,设置一个新的视图名称跳转指定页面
    -->
    <prop key="java.lang.ArithmeticException">error</prop>
    </props>
    </property>
    <!-- exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享 -->
    <property name="exceptionAttribute" value="ex"></property>
</bean>

2、基于注解的异常处理

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(ArithmeticException.class)//处理的异常
    public String handleArithmeticException(Throwable ex, Model model){
        model.addAttribute("ex",ex);
        //跳转页
        return "error";
    }
}

九、本测试使用的 index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <Meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>=========首页======</h1>
<a th:href="@{/hello}">HelloWorld</a><br/>
<a th:href="@{/error1}">异常处理跳转</a><br/>
<a href="/hello">测试绝对链接路径</a><br/>
<a th:href="@{/helloa}">测试ant风格路径</a><br/>
<a th:href="@{/demo/param(param=测试参数为中文)}">简单参数绑定 param 和 注解获取请求头、cookie信息</a><br/>
<a th:href="@{/demo/path/人品测试}">测试路径参数</a><br/>

<form th:action="@{/demo/entity}" method="post">
    姓名:<input th:type="text" name="name"> <br>
    年龄:<input th:type="text" name="age">   <br>

    <input type="submit" value="记入">
</form>

<h1>=========测试视图======</h1>
<a th:href="@{/viewDemo/forward}">转发视图</a><br/>
<a th:href="@{/viewDemo/redirect}">重定向视图</a><br/>

<h1>=========restFul风格请求测试======</h1>
<form th:action="@{/restFul01/1}" method="post">
    <input th:type="hidden" name="_method" value="put"> <br>
    <input type="submit" value="put请求">
</form>

<h1>=========文件上传下载======</h1>
<a th:href="@{/restFul01/downImg/image-2022}">图片下载</a><br/>

<form th:action="@{/restFul01/uploadFile}" th:method="post" enctype="multipart/form-data">
    文件<input  th:type="file" name="multipartfile">
    <input th:type="submit" th:value="文件上传">
</form>
</body>
</html>

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...