学习springMVC

news2024/10/5 10:05:40

第四章 Spring MVC

第一节 Spring MVC 简介

1. Spring MVC

SpringMVC是一个Java 开源框架, 是Spring Framework生态中的一个独立模块,它基于 Spring 实现了Web MVC(数据、业务与展现)设计模式的请求驱动类型的轻量级Web框架,为简化日常开发,提供了很大便利。

2. Spring MVC 核心组件

  • DispatcherServlet 前置控制器

    负责接收请求、分发请求

  • Handler 处理器

    处理器包括了拦截器、控制器中的方法等,主要负责处理请求

  • HandlerMapping 处理器映射器

    解析配置文件、扫描注解,将请求与处理器进行匹配

  • HandlerAdpter 处理器适配器

    根据请求来找到匹配的处理器,这个过程称为适配

  • ViewResolver 视图解析器

    处理器执行后得到的结果可能是一个视图,但这个视图属于逻辑视图(页面中存在逻辑代码,比如循环、判断),需要使用视图解器行处理,这个过程称为渲染视图

第二节 Spring MVC 发展演变

<!--低版本-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

1. Bean的名字或ID匹配URL请求

1.1 web.xml 配置
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <!--配置Servlet初始化参数-->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!--前置控制器要接收所有的请求,因此在容器启动的时候就应该完成初始化-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
1.2 spring-mvc.xml 配置
<!--视图解析器:在控制器返回视图的时候生效-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--视图资源的前缀-->
    <property name="prefix" value="/" />
    <!--视图资源的后缀-->
    <property name="suffix" value=".jsp" />
</bean>
<!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
1.3 编写控制器
public class UserController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        //这里使用配置的视图解析器进行解析  user => / + user + .jsp => /user.jsp
        return new ModelAndView("user");
    }
}
1.4 配置控制器
<!--通过id值匹配请求的URL-->
<bean id="/view" class="com.qf.spring.mvc.controller.UserController" />

思考:按照这种匹配请求的方式,每一个请求需要一个控制器与之对应,这与使用Servlet开发一样,会编写大量的控制器,导致开发效率极为低下,如何解决?

Spring 提供了方法名来匹配请求来解决这个问题

2. Bean的方法名匹配请求

2.1 方法名解析器

Spring 提供了控制器内的方法名的解析器 InternalPathMethodNameResolver,该解析器作用就是将方法名作为匹配URL请求的依据,与控制器关联起来

2.2 多操作控制器

Spring 提供了 MultiActionController 控制器类,供其他控制器类继承,在其子类中,开发者可以编写多个处理请求的方法,然后使用方法名解析器去匹配请求

2.3 编写控制器
public class UserMultiController extends MultiActionController {
    //这个方法就匹配 /login 请求
    //请求格式必须是 
    //ModelAndView 方法名(HttpServletRequest req, HttpServletResponse resp){}
    public ModelAndView login(HttpServletRequest req, HttpServletResponse resp){
        return new ModelAndView("login");
    }

    //这个方法就匹配 /register 请求
    public ModelAndView register(HttpServletRequest req, HttpServletResponse resp){
        return new ModelAndView("register");
    }
}
2.4 spring-mvc.xml 配置
 <!--方法名解析器-->
<bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />
<!-- /login 请求使用该bean对象处理-->
<bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">
    <property name="methodNameResolver" ref="methodNameResolver" />
</bean>
<!-- /register 请求使用该bean对象处理-->
<bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">
    <property name="methodNameResolver" ref="methodNameResolver" />
</bean>

思考:按照这种匹配请求的方式,如果一个控制器要处理多个请求,那么就会导致配置信息繁多的问题,后期难以维护,如何解决?

Spring 提供了 SimpleUrlHandlerMapping 映射器, 该映射器支持一个控制器与多个请求匹配的同时也解决了配置信息繁多的问题。

3. 简单URL处理器映射

使用SimpleUrlHandlerMapping只需要修改 spring-mvc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>

    <!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<!--    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
    <!--通过id值匹配请求的URL-->
<!--    <bean id="/view" class="com.qf.spring.mvc.controller.UserController" />-->
    <!--方法名解析器-->
<!--    <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />-->
    <!-- /login 请求使用该bean对象处理-->
<!--    <bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!-- /register 请求使用该bean对象处理-->
<!--    <bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/view">userController</prop>
                <prop key="/user/*">userMultiController</prop>
            </props>
        </property>
    </bean>
    <bean id="userController" class="com.qf.spring.mvc.controller.UserController" />
    <bean id="userMultiController" class="com.qf.spring.mvc.controller.UserMultiController" />
</beans>

思考:随着项目开发的推进,开发的业务功能越来越多,控制器的数量也会伴随着增加,请求的匹配同时也会增加,同样会造成后期难以维护的问题,如何解决呢?

Spring 提供了 DefaultAnnotationHandlerMapping 映射器,支持使用注解来匹配请求,这样就解决了请求匹配导致配置信息繁多的问题,同时还提升了开发效率。

4. 注解匹配请求

4.1 编写控制器
@Controller
public class UserAnnotationController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(){
        return "login";
    }

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public String register(){
        return "register";
    }
}
4.2 spring-mvc.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">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>

    <!--处理器映射的方式:使用bean的名字或者id的值来与请求匹配-->
<!--    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
    <!--通过id值匹配请求的URL-->
<!--    <bean id="/view" class="com.qf.spring.mvc.controller.UserController" />-->
    <!--方法名解析器-->
<!--    <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />-->
    <!-- /login 请求使用该bean对象处理-->
<!--    <bean id="/login" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!-- /register 请求使用该bean对象处理-->
<!--    <bean id="/register" class="com.qf.spring.mvc.controller.UserMultiController">-->
<!--        <property name="methodNameResolver" ref="methodNameResolver" />-->
<!--    </bean>-->
    <!--<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/view">userController</prop>
                <prop key="/login">userMultiController</prop>
                <prop key="/register">userMultiController</prop>
            </props>
        </property>
    </bean>
    <bean id="userController" class="com.qf.spring.mvc.controller.UserController" />
    <bean id="userMultiController" class="com.qf.spring.mvc.controller.UserMultiController" />-->
    <!--类上的注解处理器-->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <!--方法上的注解处理器-->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <!--扫描包,使得该包下类以及类中定义的方法上所使用的注解生效-->
    <context:component-scan base-package="com.qf.spring.mvc.controller" />
</beans>

5. 较新的版本配置

<?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">
    <!--视图解析器:在控制器返回视图的时候生效-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--视图资源的前缀-->
        <property name="prefix" value="/" />
        <!--视图资源的后缀-->
        <property name="suffix" value=".jsp" />
    </bean>
    <!--较新的版本使用该标签开启注解支持-->
    <mvc:annotation-driven />
    <!--扫描包,使得该包下类以及类中定义的方法上所使用的注解生效-->
    <context:component-scan base-package="com.qf.spring.mvc.controller" />
</beans>

第三节 Spring MVC 常用注解

1. @Controller

该注解是一个控制器的标识

@Controller
public class UserController{
    
}

2. @RequestMapping

该注解用于匹配请求

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    public int login(){
        return 1;
    }
}

3. @RequestBody

该注解只能应用在方法的参数上,用于从请求体中获取数据并注入至参数中

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    public int login(@RequestBody User user){
        return 1;
    }
}

4. @ResponseBody

该注解用于向页面传递数据

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/login", method=RequestMethod.POST)
    @ResponseBody
    public int login(@RequestBody User user){
        return 1;
    }
}

5. @RequestParam

该注解只能应用在方法的参数上,用于从请求头中获取数据并注入至参数中

@Controller
@RequestMapping("/user")
public class UserController{
    
    @RequestMapping(value="/search", method=RequestMethod.GET)
    @ResponseBody
    public List<User> searchUsers(@RequestParam(value="name") String name){
        return new ArrayList<>();
    }
}

6. @PathVariable

该注解只能应用在方法的参数上,用于从请求路径中获取数据并注入至参数中

@Controller
@RequestMapping("/user")
public class UserController{
    // /user/admin
    @RequestMapping(value="/{username}", method=RequestMethod.GET)
    @ResponseBody
    public User queryUser(@PathVariable("username") String username){
        return new User();
    }
}

7. @SessionAttributes[不重要]

该注解只能使用在类定义上,用于从将输入放入 session 中

@SessionAttributes(types=User.class) //会将model中所有类型为 User的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”}) //会将model中属性名为user1和user2的属性添加到会话中。
@SessionAttributes(types={User.class, Dept.class}) //会将model中所有类型为 User和Dept的属性添加到会话中。
@SessionAttributes(value={“user1”,“user2”},types={Dept.class}) //会将model中属性名为user1和user2以及类型为Dept的属性添加到会话中。

8. @RequestHeader

该注解只能应用在方法的参数上,用于从请求头中获取数据

@RequestMapping("/find")  
public void findUsers(@RequestHeader("Content-Type") String contentType) {//从请求头中获取Content-Type的值
}  

9. @CookieValue

该注解只能应用在方法的参数上,用于从请求中获取cookie的值

@RequestMapping("/find")  
public void findUsers(@CookieValue("JSESSIONID") String jsessionId) {//从请cookie中获取jsessionId的值
}  

10. @ControllerAdvice

该注解只能应用在类上,表示这个类就是处理异常的控制器

/**
 * 异常处理的控制器
 */
@ControllerAdvice //这个注解就是spring mvc提供出来做全局异常统一处理的
public class ExceptionController {
}

11. @ExceptionHandler

该注解只能应用在@ControllerAdvice或者说@RestControllerAdvice标识的类的方法上,用来处理异常

/**
 * 异常处理的控制器
 */
@ControllerAdvice //这个注解就是spring mvc提供出来做全局异常统一处理的
public class ExceptionController {

    @ExceptionHandler //异常处理器
    @ResponseBody //响应至页面
    public String handleException(Exception e){
        return e.getMessage();
    }
}

第四节 JSR-303

1. JSR-303 简介

JSR全称为 Java Specification Requests,表示 Java 规范提案。JSR-303是 Java 为 Java Bean 数据合法性校验提供的标准框架,它定义了一套可标注在成员变量,属性方法上的校验注解。Hibernate Validatior提供了这套标准的实现。

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.0.1.Final</version>
  <!-- 最新7.0.1.Final -->
</dependency>

2. 校验注解

注解解释注解解释
@Null必须为null@NotNull不能为null
@AssertTrue必须为true@AssertFalse必须为false
@Min必须为数字,其值大于或等于指定的最小值@Max必须为数字,其值小于或等于指定的最大值
@DecimalMin必须为数字,其值大于或等于指定的最小值@DecimalMax必须为数字,其值小于或等于指定的最大值
@Size集合的长度@Digits必须为数字,其值必须再可接受的范围内
@Past必须是过去的日期@Future必须是将来的日期
@Pattern必须符合正则表达式@Email必须是邮箱格式
@Length(min=,max=)字符串的大小必须在指定的范围内@NotEmpty不能为null,长度大于0
@Range(min=,max=,message=)元素必须在合适的范围内@NotBlank不能为null,字符串长度大于0(限字符串)

3. 应用

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.3.10</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.10</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.1.Final</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<!-- web.xml -->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
<?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:p="http://www.springframework.org/schema/p"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/" p:suffix=".jsp" />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <!--处理字符串的消息转换器-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <!--处理JSON格式的消息转换器-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <context:component-scan base-package="com.qf.spring.controller" />
</beans>
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotNull;

public class User {

    @NotNull(message = "账号不能为空")
    @Length(min = 8, max = 15, message = "账号长度必须为8~15位")
    private String username;

    @NotNull(message = "密码不能为空")
    @Length(min = 8, max = 20, message = "密码长度必须为8~20位")
    private String password;

    @Range(min = 0, max = 120, message = "年龄只能在0~120岁之间")
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.Valid;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/add")
    @ResponseBody
    public Object saveUser(@Valid User user, BindingResult result){
        if(result.hasErrors()) return result.getAllErrors();
        return 1;
    }
}

第五节 RESTFUL

1. RESTFUL 简介

REST全称为 Representational State Transfer,表示 表述性状态转移

RESTFUL有如下特点:

  • 每一个 URI 代表一种资源
  • 客户端使用GET、POST、PUT、DELETE4 个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源

2. RESTFUL 请求

/user GET => 获取用户资源
/user POST => 增加用户资源
/user PUT => 修改用户资源
/user DELETE => 删除用户资源

/user/{username} GET => 获取指定用户资源  这是RESTFUL风格中子资源的表述方式

3. Spring 对 RESTFUL 的支持

3.1 @RestController

该注解只能应用于类上,相当于@Controller 和 @ResponseBody 注解的组合。表示该类中的所有方法执行完成后所返回的结果直接向页面输出

3.2 @GetMapping
3.2 @PostMapping
3.2 @PutMapping
3.2 @DeleteMapping

第六节 静态资源处理

1. 静态资源无法访问的原因

静态资源包含html、js、css、图片、字体文件等。静态文件没有url-pattern,所以默认是访问不到的。之所以可以访问,是因为tomcat中有一个全局的servlet:org.apache.catalina.servlets.DefaultServlet,它的url-pattern是 “/”, 所以项目中不能匹配的静态资源请求,都由这个Servlet来处理。但在SpringMVC中DispatcherServlet也采用了"/" 作为url-pattern, 那么项目中不会再使用全局的Serlvet,这样就造成了静态资源不能完成访问。

2. 处理方案

2.1 方案一

DispathcerServlet 对应的 url-pattern 修改为 “/” 以外的其他匹配样式即可。比如 *.do, *.action。这样修改后,发送请求时,请求URL必须匹配 .do 或者 .action。

2.2 方案二
<!-- web.xml -->
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
  </servlet-mapping>
2.2 方案三
<!-- spring-mvc.xml -->
<!-- 
这个handler就是处理静态资源的,它的处理方式就是将请求转会到tomcat中名为default的Servlet 
-->
<mvc:default-servlet-handler/>
<!-- mapping是访问路径,location是静态资源存放的路径 -->
<mvc:resources mapping="/static/**" location="/static/" />

第七节 中文乱码处理

<?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">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <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>
</web-app>

第八节 Spring MVC工作原理

checkMultipart(request); //检测是否是多部分请求,这个只可能在文件上传的时候为真


getHandler(processedRequest); //获取处理器 => 遍历HandlerMapping,找到匹配当前请求的执行器链
//没有找到执行器链 就直接向页面报一个404
noHandlerFound(processedRequest, response);
//找到处理当前请求的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

//控制器之前执行的拦截器将先执行,如果拦截器不通过,则方法直接结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}
//控制器处理请求,可能会得到一个ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

//控制器之后的拦截器执行
mappedHandler.applyPostHandle(processedRequest, response, mv);
//处理分发的结果:这个结果就是控制器处理后的结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//拦截器在控制器给出的结果DispatcherServlet处理后执行
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1888109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

和鲸“101”计划领航!和鲸科技携手北中医,共话医学+AI 实验室建设及创新人才培养

为进一步加强医学院校大数据管理与应用、信息管理与信息系统&#xff0c;医学信息工程等专业建设&#xff0c;交流实验室建设、专业发展与人才培养经验&#xff0c;6 月 22 日&#xff0c;由北京中医药大学&#xff08;简称“北中医”&#xff09;主办&#xff0c;上海和今信息…

使用Spring Boot实现博客管理系统

文章目录 引言第一章 Spring Boot概述1.1 什么是Spring Boot1.2 Spring Boot的主要特性 第二章 项目初始化第三章 用户管理模块3.1 创建用户实体类3.2 创建用户Repository接口3.3 实现用户Service类3.4 创建用户Controller类 第四章 博客文章管理模块4.1 创建博客文章实体类4.2…

to_json 出现乱码的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

PyCharm远程开发

PyCharm远程开发 1- 远程环境说明 每个人的本地电脑环境差别很大。各自在自己电脑上开发功能&#xff0c;测试/运行正常。但是将多个人的代码功能合并&#xff0c;运行服务器上&#xff0c;会出现各种版本兼容性问题。 在实际企业中&#xff0c;一般会有两套环境。第一套是测…

2.3 主程序和外部IO交互 (文件映射方式)----IO Server实现

2.3 主程序和外部IO交互 &#xff08;文件映射方式&#xff09;----IO Server C实现 效果显示 1 内存共享概念 基本原理&#xff1a;以页面为单位&#xff0c;将一个普通文件映射到内存中&#xff0c;达到共享内存和节约内存的目的&#xff0c;通常在需要对文件进行频繁读写时…

【单片机毕业设计选题24043】-可旋转式电视支架控制系统设计与实现

系统功能: 系统操作说明&#xff1a; 上电后OLED显示 “欢迎使用电视支架系统请稍后”&#xff0c;两秒后进入正常界面显示 第一页面第一行显示 Mode:Key&#xff0c; 第二行显示 TV:Middle 短按B5按键可控制步进电机左转&#xff0c; 第二行显示 TV:Left 后正常显示 TV:…

【操作系统期末速成】 EP04 | 学习笔记(基于五道口一只鸭)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文&#xff1a;☀️☀️☀️2.1 考点七&#xff1a;进程通信2.2 考点八&#xff1a;线程的概念2.3 考点九&#xff1a;处理机调度的概念及原则2.4 考点十&#xff1a;调度方式与调度算法 一、前言&#x1f680;…

因为文件共享不安全,所以你不能连接到文件共享。此共享需要过时的SMB1协议,而此协议是不安全的 解决方法

目录 1. 问题所示2. 解决方法3. 解决方法1. 问题所示 输入共享文件地址的时候,出现如下信息: 因为文件共享不安全,所以你不能连接到文件共享。此共享需要过时的SMB1协议,而此协议是不安全的,可能会是你的系统遭受攻击。你的系统需要SMB2或更高版本截图如下所示: 2. 解决…

查看电脑显卡(NVIDIA)应该匹配什么版本的CUDA Toolkit

被串行计算逼到要吐时&#xff0c;决定重拾CUDa了&#xff0c;想想那光速般的处理感觉&#xff08;夸张了&#xff09;不要太爽&#xff0c;记下我的闯关记录。正好我的电脑配了NVIDIA独显&#xff0c;GTX1650&#xff0c;有菜可以炒呀&#xff0c;没有英伟达的要绕道了。回到正…

茗鹤APS高级计划排程系统,在集团多工厂协同生产下的应用

随着业务规模的扩大和市场的全球化&#xff0c;越来越多的企业选择“总部多工厂基地”的模式&#xff0c;此种模式大幅提升企业的产能与产量&#xff0c;有效分散风险。然后&#xff0c;与之而来的是对企业的管理提出更高的管理要求。多个生产基地不仅面临集团下发的周期性计划…

[漏洞分析] CVE-2024-6387 OpenSSH核弹核的并不是很弹

文章目录 漏洞简介漏洞原理补丁分析漏洞原理 漏洞利用漏洞利用1: SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, from 2005) [无ASLR无NX]漏洞利用原理漏洞利用关键点 漏洞利用2: SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, from 2006) [无ASLR…

Python模拟火焰文字效果:炫酷的火焰字动效

文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame定义火焰效果类主循环 完整代码 引言 火焰文字效果是一种炫酷的视觉效果&#xff0c;常用于广告、游戏和艺术设计中。在这篇博客中&#xff0c;我们将使用Python创建一个火焰文字的动画效果。通过利用Py…

元素的宽度和高度未知,如何水平垂直居中,3个小办法。

在前端开发中&#xff0c;如果元素的宽度和高度未知&#xff0c;但需要将其水平和垂直居中&#xff0c;可以使用以下方法之一&#xff1a; 使用Flexbox布局&#xff1a; Flexbox是一种强大的布局模型&#xff0c;可以轻松实现元素的居中。可以通过以下CSS代码实现水平和垂直居…

# Sharding-JDBC从入门到精通(7)- Sharding-JDBC 公共表 与 读写分离

Sharding-JDBC从入门到精通&#xff08;7&#xff09;- Sharding-JDBC 公共表 与 读写分离 一、Sharding-JDBC 公共表 1、公共表 公共表属于系统中数据量较小&#xff0c;变动少&#xff0c;而且属于高频联合查询的依赖表。参数表、数据字典表等属于此类型。可以将这类表在每…

LabVIEW汽车ECU测试系统

开发了一个基于LabVIEW开发的汽车发动机控制单元&#xff08;ECU&#xff09;测试系统。该系统使用了NI的硬件和LabVIEW软件&#xff0c;能够自动执行ECU的功能测试和性能测试&#xff0c;确保其在不同工作条件下的可靠性和功能性。通过自动化测试系统&#xff0c;大大提高了测…

深度网络现代实践 - 深度前馈网络之结构设计篇

序言 深度网络结构设计作为人工智能领域的基石&#xff0c;正引领着技术创新的浪潮。通过模拟人脑神经元间的复杂连接&#xff0c;深度神经网络展现了卓越的特征学习与模式识别能力。随着大数据与计算能力的提升&#xff0c;设计高效、精准且泛化能力强的深度网络结构成为研究…

Linux基础 - LNMP 架构部署动态网站环境

目录 零. 简介 一. 部署 二. 安装 Nginx 三. 安装MySQL 四. 安装PHP 五. 配置网站目录 六. 测试环境 零. 简介 LNMP 是指 Linux Nginx MySQL PHP 这一组合架构&#xff0c;用于部署动态网站环境。 Linux 作为操作系统&#xff0c;提供了稳定、安全和高效的基础平台。…

Linux基础 - MariaDB 数据库管理系统

目录 零. 简介 一. 安装 二. 基本使用 1. 设置root密码 2. 创建库 3. 创建表 4.添加数据 5. 查看数据 三. 管理表单及数据 四. 数据库的备份及恢复 零. 简介 MariaDB 是一种流行的开源数据库管理系统&#xff0c;它是 MySQL 的一个分支。 MariaDB 保留了与 MySQL 的…

学习笔记——动态路由——OSPF(工作原理)

九、OSPF协议的工作原理 1、原理概要 (1)相邻路由器之间周期性发送HELLO报文&#xff0c;以便建立和维护邻居关系。 (2)建立邻居关系后&#xff0c;给邻居路由器发送数据库描述报文(DD)&#xff0c;也就是将自己链路状态数据库中的所有链路状态项目的摘要信息发送给邻居路由器…

提高页面性能:懒加载和预加载都是啥原理。

懒加载&#xff08;Lazy Loading&#xff09;和预加载&#xff08;Preloading&#xff09;是在 Web 开发中常用的两种优化技术&#xff0c;用于提高页面性能和用户体验。那他们之间有什么不同&#xff0c;又有哪些应用场景呢&#xff0c;本文给小伙伴们分享下。 一、懒加载 懒…