工作原理


1.在maven中导入springMVC依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
2.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"><!-- 置顶注册编码过滤器,设置编码之前不能获取任何请求的数据--><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置请求体的编码格式--><init-param><!-- 设置CharacterEncodingFilter中Encoding属性的值--><param-name>encoding</param-name><!-- 将值改为UTF-8--><param-value>UTF-8</param-value></init-param><!-- 设置响应体的编码格式--><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><!-- 过滤请求范围--><url-pattern>/*</url-pattern></filter-mapping><!-- 注册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><!-- 配置SpringMVC核心控制器,对浏览器发送的请求统一处理--><servlet><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置SpringMVC的配置文件的位置和名称--><init-param><!-- 上下文配置路径--><param-name>contextConfigLocation</param-name><!-- 类路径--><param-value>classpath:springMVC.xml</param-value></init-param><!-- 设置核心控制器初始化时间当值为0或者大于0时,表示容器在应用(服务器)启动时就加载并初始化当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--启动spring容器--><!--指定spring配置文件的位置--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener></web-app>
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.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--扫描组件context命名空间:扫描多个包用逗号隔开--><context:component-scan base-package="com.kgc"/><!--配置Thymeleaf视图解析器--><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><!-- 设置视图解析器的优先级--><property name="order" value="1"/><!-- 解析视图时所用的编码格式--><property name="characterEncoding" value="UTF-8"/><!-- 模板--><property name="templateEngine"><!-- 内部bean为模板属性赋值--><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><!-- 解析视图的策略--><!--视图前缀--><property name="prefix" value="/templates/"/><!--视图后缀--><property name="suffix" value=".html"/><!-- 模板中的模型--><property name="templateMode" value="HTML5"/><!-- 页面的编码格式--><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean><!-- 视图控制器:view-controllerpath:设置处理请求的地址view-name:设置请求地址对应的视图名称--><!-- <mvc:view-controller path="/file" view-name="file"/>--><mvc:view-controller path="/upFile" view-name="upFile"/><!-- 当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要开启mvc注解驱动--><!-- 开启mvc的注解驱动--><mvc:annotation-driven/><!-- 静态页面放行--><mvc:default-servlet-handler/><!-- 配置文件上传解析器,将上传的文件封装为multipartFile--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置文件上传的默认编码格式--><property name="defaultEncoding" value="utf-8"/><!-- 单个文件大小限制(byte)--><property name="maxUploadSizePerFile" value="#{10*1024*1024}"/><!-- 整个请求大小限制(byte)--><property name="maxUploadSize" value="#{100*1024*1024}"/></bean><!--配置拦截器--><!-- <mvc:interceptors>--><!-- <!–配置拦截器,多个拦截器时,顺序执行–>--><!-- <mvc:interceptor>--><!-- <!–要拦截的具体的方法–>--><!-- <mvc:mapping path="/**"/>--><!-- <!–不去拦截的方法–>--><!-- <mvc:exclude-mapping path="/"/>--><!-- <!–配置拦截器对象–>--><!-- <bean class="com.kgc.interceptors.FirstInterceptor"/>--><!-- </mvc:interceptor>--><!-- </mvc:interceptors>--><!-- 配置异常处理器--><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><!--key里是异常的全类名,value为视图名称视图解析器会解析出现该异常时会自动跳转到设置的视图页面--><prop key="java.lang.ArithmeticException">error</prop></props></property><!-- value的值为存储在共享域中的键,值为发生异常的异常信息--><property name="exceptionAttribute" value="ex"/></bean></beans>
- 浏览器发送请求,若请求地址符合前端控制器的url-pattern(web.xml中的url-pattern标签),该请求就会被前端控制器DispatcherServlet处理。
- 前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中
- @RequestMapping注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。
- 处理请求的方法需要返回一个字符串类型的视图名称
- 该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径
- 通过Thymeleaf对视图进行渲染,最终转发到视图所对应页面
@RequestMapping注解
属性:
- value:通过请求地址来匹配请求 (/地址)
- method:通过请求方式来匹配请求 (get/post)
- params:通过请求参数来匹配请求
- headers:通过请求头信息来匹配请求
派生注解
1、对于处理指定请求方式的控制器方法,SpringMVC中提供 了@RequestMapping的派生注解
- 处理get请求的映射—>@GetMapping
- 处理post请求的映射—>@PostMapping
- 处理put请求的映射—>@PutMapping
- 处理delete请求的映射—>@DeleteMapping
2、常用的请求方式有get, post, put, delete
但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理
若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilter
SpringMVC支持ant风格的路径
value=””中可以这样写路径
- ? :表示任意的单个字符
- *:表示任意的0个或多个字符
- **:表示任意的一层或多层目录
@RequestParam注解
将请求参数和控制器方法形参创建映射关系
请求参数注解:
- value:和请求参数名一致
- name:和请求参数名一致
- required:自动装配 默认true,当参数值为null会400错误
- defaultValue:当请求参数为null或者空字符串时
@RequestHeader注解
将请求头信息和控制器方法形参创建映射关系
属性和@RequestParam注解一致@CookieValue注解
将cookie数据和控制器方法形参创建映射关系注册过滤器处理中文乱码问题
<!-- 注册过滤器--><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置请求体的编码格式--><init-param><!-- 设置CharacterEncodingFilter中Encoding属性的值--><param-name>encoding</param-name><!-- 将值改为UTF-8--><param-value>UTF-8</param-value></init-param><!-- 设置响应体的编码格式--><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><!-- 过滤请求范围--><url-pattern>/*</url-pattern></filter-mapping>
CharacterEncodingFilter类中三个属性和一个方法
```java @Nullable //编码格式 private String encoding; //请求编码处理 private boolean forceRequestEncoding; //响应编码处理 private boolean forceResponseEncoding; //默认是不开启处理 public CharacterEncodingFilter() {
}this.forceRequestEncoding = false;this.forceResponseEncoding = false;
//过滤器执行方法
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//先看是否设置了编码格式,没设置默认为null
String encoding = this.getEncoding();
if (encoding != null) {
//看是否开启响应/请求编码格式处理
if (this.isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (this.isForceResponseEncoding()) {response.setCharacterEncoding(encoding);}}filterChain.doFilter(request, response);}
<a name="uV0XB"></a>## session 的钝化和活化假设我们在淘宝中用户过多的时候,虽然 session 没有下限,但 session 的数量就会不断增多。之后就会导致内存无法承受,此时就会有一些 session 长时间都没有活动。服务器启动时就会将这些很久没有活动的 session 放到硬盘上,让内存给空出来。就会使得很多的session被保存到硬盘上以此来空出内存。而即便之后需要再次访问 session,它就会再次从硬盘中将 session给放到内存中来使用。这样用户就不会感觉到自己掉线了。这个过程就是 session 的钝化和活化。<br />而钝化和活化最终都是把 session 保存到硬盘中,再从硬盘中回到内存中。<br />但是他们和session序列化、反序列化发生的时间点不一样。session序列化反序列化是关闭和启动服务器,session钝化和活化是没有关闭和启动服务器就完成了<a name="smy2X"></a>## ModelAndView对象model:用于向请求域共享数据<br />view:用于设置视图,实现页面跳转<br />ModelAndView mav=new ModerlAndView();<br />mav.addObjet(String name,Object value)<br />mav.setViewName(String name)<a name="f2cuC"></a>## 重定向和转发转发:forward:/请求名称 创建internalResourceView视图<br />重定向:redirect:/请求名称 创建RedirectView视图<br />(不支持视图解析器)<a name="xCgoA"></a>## RESTFul[<br />](https://blog.csdn.net/qq_39671996/article/details/124352227)<br /><br /><a name="SNTc9"></a>### 日期格式化@DateTimeFormat (pattern = "yyyy-MM-dd" )<br />在实体类date属性上加<br />@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")//主要是限制前台的时间格式<br />@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")//主要是控制后台到前台的时间格式<a name="Q7Go1"></a>## HttpMessageConverter报文信息转换器@RequestBody RequestEntity<br />@ResponseBody ResponseEntity<br />在控制器方法上加@ResponseBody 注解后返回值为响应体<br />与Response.getWriter().print("响应体")效果相同---**ResponseEntity**<br />ResponseEntity的优先级高于@ResponseBody。在不是ResponseEntity的情况下才去检查有没有@ResponseBody注解。如果响应类型是ResponseEntity可以不写@ResponseBody注解,写了也没有关系。简单的说1. @ResponseBody可以直接返回Json结果,1. @ResponseEntity不仅可以返回json结果,还可以定义返回的HttpHeaders和HttpStatus<a name="xPMtn"></a>### 解决响应体为json格式导入依赖<br />_<!-- jackson依赖处理json格式--><br /> _<**dependency**><br /> <**groupId**>com.fasterxml.jackson.core</**groupId**><br /> <**artifactId**>jackson-databind</**artifactId**><br /> <**version**>2.12.1</**version**><br /> </**dependency**><br />在springmvc配置文件中开启<br />_<!-- 开启mvc的注解驱动--><br />_<**mvc:annotation-driven**/><br />json的两种格式对象和数组<a name="ppNIJ"></a>### @RestController派生注解@RestController注解是SpringMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解<a name="C5Y24"></a>### ResponseEntity实现文件下载```java@RequestMapping("/xiazai/{filename}")@ResponseBodypublic ResponseEntity<byte[]> testResponseEntity(@PathVariable("filename") String filename, HttpSession session) throws IOException {//获取ServletContext对象ServletContext servletContext = session.getServletContext();//获取服务器中文件的真实路径String realPath = servletContext.getRealPath("/photo/"+filename);//创建输入流InputStream is = new FileInputStream(realPath);//创建字节数组byte[] bytes = new byte[is.available()];//将流读到字节数组中is.read(bytes);//创建HttpHeaders对象设置响应头信息MultiValueMap<String, String> headers = new HttpHeaders();//设置要下载方式以及下载文件的名字headers.add("Content-Disposition", "attachment;filename="+filename);//设置响应状态码HttpStatus statusCode = HttpStatus.OK;//创建ResponseEntity对象ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);//关闭输入流is.close();return responseEntity;}
上传功能
<dependencies>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<form action="/addfile" method="post" enctype="multipart/form-data">选择文件:<input type="file" name="photo"><br/><input type="submit" value="上传"></form>
@RequestMapping("/addfile")public String addfile(MultipartFile photo,HttpSession session)throws IOException{//获取上传的文件名String filename = photo.getOriginalFilename();//截取文件后缀名String hzm=filename.substring(filename.lastIndexOf("."));String uuid= UUID.randomUUID().toString();//根据uuid生成的唯一文件名String finalName=uuid+hzm;//将文件名保存到数据库中fileServce.addFile(new File(null,finalName));//通过ServletContext获取服务器中photo目录的路径ServletContext servletContext = session.getServletContext();String photoPath = servletContext.getRealPath("photo");//查看服务器中是否有photo目录java.io.File file = new java.io.File(photoPath);if (!file.exists()){//若不存在,则创建目录file.mkdir();}//路径加文件名String finalPath =photoPath+ java.io.File.separator+finalName;//上传文件photo.transferTo(new java.io.File(finalPath));//重定向页面return "redirect:/file";}
删除文件
@RequestMapping("/deleteFile/{fileid}")public String deleteFile(@PathVariable("fileid")Integer fileid,HttpSession session){//获取删除的文件id和名称File fileById = fileServce.getFileById(fileid);String filename = fileById.getFilename();//通过ServletContext获取服务器中photo目录的路径ServletContext servletContext = session.getServletContext();String realPath = servletContext.getRealPath("photo");//拼接photo目录路径和文件名String finalName=realPath+"/"+filename;//创建io对象,删除文件java.io.File file=new java.io.File(finalName);boolean delete = file.delete();//将数据库中的文件也删除fileServce.deleteFile(fileid);//重定向页面return "redirect:/file";}
拦截器

在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用
过滤器和拦截器的区别?
过滤器(filter):
1) filter属于Servlet技术,只要是web工程都可以使用
2) filter主要对所有请求过滤
3) filter的执行时机早于Interceptor
拦截器(interceptor)
1) interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
2) interceptor通常对处理器Controller进行拦截
3) interceptor只能拦截dispatcherServlet处理的请求
应用场景
1)日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2)权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
3)性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4)通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。
拦截器方法说明
preHandle方法
作用:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。<br /> 执行时机:在处理器方法执行前执行 <br /> 方法参数:<br /> 1)request请求对象<br /> 2)response响应对象<br /> 3)handler拦截到的方法处理
postHandle方法
作用:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改<br /> 执行时机:在处理器的方法执行后,视图渲染之前<br /> 方法参数:<br /> 1)request请求对象<br /> 2)response响应对象<br /> 3)handler拦截到的处理器方法<br /> 4)ModelAndView处理器方法返回的模型和视图对象,可以在方法中修改模型和视图
afterCompletion方法
作用:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象<br /> 执行时机:视图渲染完成后(整个流程结束之后)<br /> 方法参数:<br /> 1)request请求参数<br /> 2)response响应对象<br /> 3)handler拦截到的处理器方法<br /> 4)ex异常对象
在SpringMVC中配置拦截器
<!--配置拦截器--><mvc:interceptors><!--配置拦截器,多个拦截器时,顺序执行--><mvc:interceptor><!--要拦截的具体的方法--><mvc:mapping path="/**"/><!--不去拦截的方法--><mvc:exclude-mapping path="/"/><!--配置拦截器对象--><bean class="com.kgc.interceptors.FirstInterceptor"/></mvc:interceptor></mvc:interceptors>
在SpringMVC中配置异常处理器
<!-- 配置异常处理器--><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><!--key里是异常的全类名,value为视图名称视图解析器会解析出现该异常时会自动跳转到设置的视图页面--><prop key="java.lang.ArithmeticException">error</prop></props></property><!-- value的值为存储在共享域中的键,值为发生异常的异常信息--><property name="exceptionAttribute" value="ex"/></bean>
基于注释配置异常处理器
@ControllerAdvice 将当前类标识为异常处理组件
@ExceptionHandler 设置所标识方法处理的异常(异常名称.class)
//将当前类标识为异常处理组件@ControllerAdvicepublic class ExceptionTest {//设置所标识方法处理的异常(异常名称.class)@ExceptionHandler(ArithmeticException.class)//exception内是异常具体信息public String ex(Exception exception, Model model){model.addAttribute("ex",exception);return "error";}}
Spring MVC五大组件及作用
DispatcherServlet
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
HandlerMapping
HandlerMapping 是处理器映射,它的作用是请求派发,负责请求和控制器建立对应的关系。它是由 DispatcherServlet 调用,DispatcherServlet 会从容器中取出所有 HandlerMapping 实例并遍历,让 HandlerMapping 实例根据自己实现类的方式去尝试查找 Handler。也就是说,DispatcherServlet要将一个请求交给哪个特定的Controller,它需要咨询一个Bean,这个Bean的名字为“HandlerMapping”。
Controller
控制器,负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。
ModelAndView
封装数据信息和视图信息的模型。使用ModelAndView类用来存储处理完后的结果数据,以及显示该数据的视图。从名字上看ModelAndView中的Model代表模型,View代表视图,这个名字就很好地解释了该类的作用。业务处理器调用模型层处理完用户请求后,把结果数据存储在该类的model属性中,把要返回的视图信息存储在该类的view属性中,然后让该ModelAndView返回该Spring MVC框架。框架通过调用配置文件中定义的视图解析器,对该对象进行解析,最后把结果数据显示在指定的页面上。
ViewResolver
视图解析器,ViewResolver 的主要作用是把一个逻辑上的视图名称解析为一个真正的视图。
五大组件的关系
DispatcherServlet收到请求后,依据HandlerMapping的配置,调用相应的Controller来处理,Controller将处理结果封装成ModelAndView对象,返回给DispatcherServlet,DispatcherServlet依据ViewResolver的解析,调用相应的视图对象,(如jsp)来生成相应的页面。

