• 将url映射到Java类或则Java类的方法
  • 封装用户提交的数据
  • 处理请求— 调用相关的业务处理—封装响应数据
  • 将响应数据进行渲染 .jsp / html 等表示层数据

Spring的Web框架围绕DispatcherServlet设计,DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java5或者以上版本的用户可以采用基于注解的声明方式**

客户端请求处理流程

  1. 客户端向前端控制器发送请求。
  2. 前端控制器接收客户端请求信息。
  3. 前端控制器调用代理对象,把请求转发给用户自定义控制器处理。
  4. 用户自定义控制器处理请求,并把处理结果通过模型对象返回给前端控制器。
  5. 前端控制器把模型数据发给视图模块进行处理。
  6. 视图模块把结果返回给前端控制器
  7. 其那段控制器把最终的视图信息通过流返回给客户端。

DespatcherServlet

  • 前端控制器DespacherServlet 中包含一个IoC容器Servlet WebApplicationContext ,这个IoC容器可能指向它的父容器———-Root WebApplicationContext

  • DespatcherServlet 继承自HttpServlet, 实现了javax.servlrt.Servlet接口。 所以本质上DespatcherServlet 也是一个Servlet

功能

  • 基于JavaBean的配置机制
  • 使用后HandlerMapping 的实现类,提前处理对控制器的请求路由。HandlerMapping 作为Bean对象由IoC容器统一管理
  • 使用HandlerAdapter 处理请求,HandlerAdapter 也是作为Bean对象由IoC容器统一管理。
  • 前端控制器异常由HandlerExceptionResolver 解析。可以映射异常到指定的错误业。
  • 视图解析策略由配置的ViewResolver 类来处理。它可以把试图名字解析成视图对象。
  • 如果用户没有提供视图对象或视图名字, 使用RequestToViewNameTranslator 配置,可以把请求转换到相应的视图对象。
  • 前端控制器使用MultipartResolver 的实现类处理实体文件的上传。
  • 国际化LocaleResolver
  • 主题策略ThemeResolver

web.xml

  • 使用注解开发时, web.xml几乎是固定格式
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <!--注册Servlet-->
  7. <servlet>
  8. <servlet-name>SpringMVC</servlet-name>
  9. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  10. <!--关联配置文件-->
  11. <init-param>
  12. <param-name>contextConfigLocation</param-name>
  13. <param-value>classpath:spring-mvc.xml</param-value>
  14. </init-param>
  15. <!--启动顺序, 数字越小,启动越早 -->
  16. <load-on-startup>1</load-on-startup>
  17. </servlet>
  18. <!--所有请求都会被SpringMVC拦截-->
  19. <servlet-mapping>
  20. <servlet-name>SpringMVC</servlet-name>
  21. <url-pattern>/</url-pattern>
  22. </servlet-mapping>
  23. </web-app>

spring-mvc.xml

  • 这个配置文件也几乎是固定格式不需要什么修改
  • 需要特别注意的是版本问题,否者会报2.4错误

将下面的第8行和第十行,spring-context spring-mvc 版本配置为与上面web.xml中web-app 相同

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns:mvc="http://www.springframework.org/schema/mvc"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. https://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context
  8. https://www.springframework.org/schema/context/spring-context-4.0.xsd
  9. http://www.springframework.org/schema/mvc
  10. https://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
  11. <!--自动扫描包, 让指定包下面的注解生效,由IoC容器统一管理-->
  12. <context:component-scan base-package="code"/>
  13. <!--过滤,让SpringMVC不处理静态资源(.css .js .html .mp3...)-->
  14. <mvc:default-servlet-handler/>
  15. <!--
  16. 支持MVC注解驱动
  17. 在Spring中使用@RequestMapping 注解来完成映射关系
  18. 想要使@RequestMapping注解生效,必须向上向下文中注册DefaultAnnotationHandlerMapping
  19. 和一个AnnotationHandlerMapping 实例, 这两个实例分别在类处理级别和方法处理级别使用
  20. :annotation-driven 自动完成上述两个实例的注入
  21. -->
  22. <mvc:annotation-driven/>
  23. <!--视图解析器-->
  24. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  25. id="internalResourceViewResolver">
  26. <!--前缀-->
  27. <property name="prefix" value="/WEB-INF/jsp/"/>
  28. <!--后缀-->
  29. <property name="suffix" value=".jsp"/>
  30. </bean>
  31. </beans>

示例

  • 在下面的这段代码中包含了SpringMVC的编码流程
  • 首先@Contorller 确定为一个组件,在位置文件的扫描文件夹中 <context:component-scan base-package="code"/> 这里的code 就是要扫面组件的包。
  • @RequestMapping(“/h1”) 代表了HTTP请求映射, 接收到 “/h1” 的请求之后会映射到设个方法上面
  • Model 是一个视图对象
  • 返回结果会被视图解析器处理,如上面配置文件里面的,返回结果会到前缀目录根据返回的String匹配相应的后缀文件,完成响应
  1. @Controller
  2. public class HelloBiz {
  3. @RequestMapping("/h1")
  4. public String sayHello(Model model){
  5. model.addAttribute("name", "Hello");
  6. return "hello";
  7. //返回结果会被视图解析器处理
  8. }
  9. }

Controller控制器

  • 控制器负责提供访问应用程序的行为, 通常通过接口定义或注解定义两种方法实现
  • 控制器负责解析用户的请求并将其转换为一个模型
  • 在SpringMVC中一个控制器类可以包含多个方法
  • 在SpringMVC中,对于Controller的配置方式有很多种

Controller接口

Controller 是一个接口,在org.springframework.web.servlet.mvc 包下接口中只有一个方法。

  1. public interface Controller {
  2. @Nullable
  3. ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
  4. }

—— 实现该接口的类获得控制器功能

——- 方法作用为:处理请求且返回一个模型与视图对象

  1. public class Controller1 implements Controller {
  2. public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
  3. ModelAndView mv = new ModelAndView();
  4. mv.addObject("name", "hello");
  5. mv.setViewName("hello");
  6. return mv;
  7. }
  8. }
  1. <bean name="hello" class="code.Controller1"/>

如上,实现了Controller接口 在新建了ModelAndView 之后也可以返回一个视图

但是这种方法有一个缺点,,,,一个控制器只能写一个方法,如果要多个方法则需要定义多个Controller

@Controller 注解

由于Controller 接口的缺点 ,@Controller 可以很好的弥补这一不足之出

  1. @Component 组件
  2. @Service service
  3. @controller controller
  4. @Repository dao
  • Spring 可以使用扫描机制来找到应用程序中所有基于注解的控制器类, 为了Spring能找到你的控制器,需要在配置文件中声明组件扫描
  1. <context:component-scan base-package="code"/>
  • 注解实现
  1. @Controller
  2. //@Controller注解的类会自动添加到Spring的上下文中 这个类会被Spring接管
  3. public class HelloBiz {
  4. //映射访问路径
  5. @RequestMapping("/h1")
  6. public String sayHello(Model model){
  7. //SpringMVC 会自动实例化一个Model对象用于视图中船只
  8. model.addAttribute("name", "Hello");
  9. //返回视图位置
  10. return "hello";
  11. }
  12. }
  • 被这个注解的类中的所有方法,如果返回值是String,并且有具体页面可以跳转,那么就会被 视图解析器解析

关于@Controller作用域

  • 在没有使用它的属性信息,默认为单例模式,在控制器中注入其他单例对象不受影响
  • @controller还包含了以下作用域
  1. @Controller
  2. @Scope("prototype") //原型作用域
  3. @RequestScope //request作用域
  4. @SessionScope //session 作用域
  5. @ApplicationScope //application作用域

(作用域在Spring中有解释)

RestFul 风格

  1. 概念:Restful 就是一个资源定位及资源操作的风格,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
  2. 操作资源:
  3. 传统:`http://127.0.0.1/item?id=1&b=0`
  4. RestFul 操作资源 `http://127.0.0.1/item/1/0`

可以通过不同的请求方式来实现不同的效果(地址一样但功能不同)

  1. @RequestMapping("/h1/{a}/{b}")
  2. public String sayHello(@PathVariable int a, @PathVariable int b, Model model){
  3. model.addAttribute("name", "Hello");
  4. return "hello";
  5. }

@PathVarible 注释可以让参数的值对应分割请求参数

优点:

  1. 1. 使路径变得更加简洁
  2. 2. 获得参数更加方便, 框架会自动转换类型
  3. 3. 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法。

@PathVarible 注解, 这个注解适用于RESTFul 风格的Web 站点, 它通过URL中存放的变量传递参数。在使用的时候当变量名与参数名不一致的时候需要特别说明)

@RequestMapping

  • @RequestMapping 注解映射HTTP 的 URL

  • SpringMVC 的 @RequestMapping 注解能够处理HTTP 请求的方法, 比如GET , PUT, POST, DELETE, 以及PATCH。

  • 所有地址栏请求默认都是HTTP GET

  • RequestMapping 有一个produces 属性, 他表示生产媒体的类型

  • params 属性表示只有HTTP 请求包含指定的参数值, 映射方法才会处理请求

  • handers 属性相同于params 而它可以携带很多的信息

  • @RequestMapping的value属性和path属性在Servlet环境下是等效的 代表的是映射URL

model 属性与HTTP方法相对应。可延伸出下面几种注解:

  1. @GetMapping
  2. @PostMappong
  3. @PutMapping
  4. @DeleteMapping
  5. @PatchMapping

@GetMapping 是一个组合注解 其实他就是一个:

  1. //使用method 属性可以指定请求的类型
  2. @RequestMapping(Value="***", method=RequestMethod.GET);

类型不一致的话会报一个405 错误

上面的注解要生效必须在配置文件中增加

  1. <mvc:annotation-driven/>

原因:

  1. 支持MVC注解驱动<br />

在Spring中使用@RequestMapping 注解来完成映射关系想要使@RequestMapping 注解生效,必须向上向下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationHandlerMapping 实例, 这两个实例分别在类处理级别和方法处理级别使用 <mvc:annotation-driven/>自动完成上述两个实例的注入

ViewResolver视图解析器

  • 在Spring MVC控制器中,所有的客户端请求处理方法(Action)必须解析出一个逻辑视图名称,无论是显式的(返回String,View或ModelAndView)还是隐式的(基于约定的,如视图名就是方法名)。视图解析器的作用是将逻辑视图转为物理视图,所有的视图解析器都必须实现ViewResolver接口。

  • Spring处理视图最重要的两个接口是ViewResolver和View。ViewResolver接口在视图名称和真正的视图之间提供映射关系; 而View接口则处理请求将真正的视图呈现给用户。

ModelAndView使用

  • 设置ModelAndView 对象, 根据view的名称,和视图解析器跳转到指定的页面。
  • 页面 : {视图解析器前缀} + viewName + {视图解析器后缀}
  1. <!--视图解析器-->
  2. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  3. id="internalResourceViewResolver">
  4. <!--前缀-->
  5. <property name="prefix" value="/WEB-INF/jsp/"/>
  6. <!--后缀-->
  7. <property name="suffix" value=".jsp"/>
  8. </bean>

原生的HttpServlet 不通过视图解析器同样可以实现跳转如下

  1. @RequestMapping("/h1")
  2. public String sayHello(HttpServletRequest request, HttpServletResponse response){
  3. request.setAttribute("name","Hello");
  4. return "hello";
  5. }

通过SpringMVC 来实现转发和从定向

  • 无需视图解析器
  1. @RequestMapping("/h1")
  2. public String sayHello(Model model){
  3. model.addAttribute("name", "name");
  4. //转发 这里路径需要使用全限命名
  5. return "/hello";
  6. }
  1. @RequestMapping("/h1")
  2. public String sayHello(Model model){
  3. model.addAttribute("name", "name");
  4. //转发
  5. return "forword:/hello";
  6. }

以上两种通过 隐性的 “/” 和 显性的 “forword:” 实现转发

  1. @RequestMapping("/h1")
  2. public String sayHello(Model model){
  3. model.addAttribute("name", "name");
  4. //重定向
  5. return "redirect:/hello";
  6. }

通过redirect 实现重定向

  • 在又视图解析其得情况下

    • 在又试图解析情况下直接写路径名默认为转发
  1. @RequestMapping("/h1")
  2. public String sayHello(Model model){
  3. model.addAttribute("name", "name");
  4. return "hello";
  5. }

重定向加上redirect 即可

  1. @RequestMapping("/h1")
  2. public String sayHello(Model model){
  3. model.addAttribute("name", "name");
  4. return "redirect:hello";
  5. }

@RequestParam

  • @RequestParam 的作用是绑定HTTP 请求参数到控制器的方法参数

  • 当HTTP 中的请求参数与控制器中的映射方法名不一致的时候,必须使用@RequestParam进行转换(下一条数据处理中有体现)

  • 此外@RequestParam还可以设置默认值,示例中HTTP 请求中没有name 参数的时候就会将name 默认设置为“qzw”

  1. //当请求中没有这个请求参数时使用默认值
  2. public String sayHello(@RequestParam(name = "name", defaultValue = "qzw") String name, Model model) {
  3. ...
  4. }

SpringMVC : 数据处理

处理提交数据

  1. 1. 提交的域名称和处理方法的参数名一致
  2. url: [http://localhost:8080/hello?name=xxx](http://localhost:8080/hello?name=xxx)
  3. 处理方法:
  1. @RequestMapping("/h1")
  2. public String sayHello(String name, Model model){
  3. //这里会自动对应到参数名name 直接取值赋值
  4. }
  1. 提交的域名称和处理方法的参数名不一致
    @RequestParam(“username”) 注解
    url:http://localhost:8080/hello?username=xxx
  1. @RequestMapping("/h1")
  2. public String sayHello(@RequestParam("username") String name, Model model){
  3. //上传参数为username 也会自动对应道String name 自动取值赋值
  4. }
  1. 3. 提交的是一个对象
  • 要求提交的表单域和对象的属性名一致,参数使用对象即可
  1. public class User {
  2. private String name;
  3. private int age;
  4. private int id;
  5. }
  1. @RequestMapping("/h1")
  2. public String sayHello(User user, Model model){
  3. }
  • 如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null

处理返回的数据

  • ModelAndView
  • ModelMap
  • Model

三种方式使用起来都差不多,主要区别如下:

  1. 1. Mdoel 只有寥寥几个方法只适合用于存储数据,简化了新手对于Model对象的操作和理解
  2. 2. ModelMap 继承了 LonkedMap 除了实现了自身的一些方法, 同样继承了 LinkedMap 的方法和特性
  3. 3. ModelAndView 可以在存储数据的同时可以设置返回对象的点的逻辑视图, 进行控制和地底层的跳转

控制器方法的返回类型

  • ModelAndView

    • 包含模型和视图两部分数据(还有两个数据类型model view 分别返回模型和视图)
  • String

    • 解析为视图名字或者路径
  • void

    • 空类型,可以使用ServletResponse直接写数据
  • Object

    • 通过配置Object 最后都是返回的Json 格式响应回去

……

乱码过滤器

SpringMVC提供了过滤器, 直接在web.xml 中配置即可

  1. <!--SpringMVC 的乱码过滤器 设置编码 -->
  2. <filter>
  3. <filter-name>encoding</filter-name>
  4. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  5. <init-param>
  6. <param-name>encoding</param-name>
  7. <param-value>UTF-8</param-value>
  8. </init-param>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>encoding</filter-name>
  12. <url-pattern>/*</url-pattern>
  13. </filter-mapping>
  • **需要注意一下 “/” 和 “/“ 的区别

@RequestBody

  • @RequestBody 注解表明了方法参数与HTTP 请求体数据绑定

  • @RequestBody 主要用来接收 前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。

  • 在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

  1. @RequestMapping("/h1")
  2. public String sayHello(@RequestBody String Jstr) throws JsonProcessingException {
  3. ObjectMapper mapper = new ObjectMapper();
  4. Bean str = mapper.readValue(Jstr,Bean.class);
  5. return "hello";
  6. }

@ResponseBody

  • 将返回信息直接写入响应体中
  • 使用了该注解的方法不会走视图解析器, 会直接返回一个字符串对象
  1. @RequestMapping("/h1")
  2. @ResponseBody
  3. public String sayHello(@RequestParam("username") String name, Model model){
  4. model.addAttribute("name", "name");
  5. return "hello";
  6. }

会发送一个响应体会到前端, 响应体里面包含了 ”hello“ 字符串

  • 在类上面使用@RestController 注解表示该类里面的所有方法都会走视图解析器, 都是返回一个字符串
  1. @RestController
  2. public class HelloBiz {
  3. ...
  4. }

@RestController

@ModelAttribute

更简洁, 可读性更强

  • 注解方法

  • 表明这个方法主要用于添加一个或多个 model 属性 , 用ModelAttribute 注解的方法会在此控制器的所有@requestMapping 方法前执行 ,一个控制器允许多个ModelAttribute 存在
    • 注解方法参数

  • 使用ModelAttribute 注解参数时,表明这个参数应该从model 中获取。 如果model 中没有该对象就新建一个对象加入到mdoel 当中, 如果找到了对应名称的对象,这个对象的属性值应当从请求参数中按名字匹配查找

@SesionAttributes and @SessionAttribute

  • @SessionAttributes 注解用于在会话中存储model 中指定名称的属性, 用在类级别它可以同时存储多个对象。
  1. @SessionAttributes(value = {"user", "shopcar"})
  2. public class HelloBiz { ... }
  3. //从Model 中提取user 属性和 shopcar 对象
  1. public String test(@SessionAttribute String name){ ... }
  2. //从会话中查找 name 对象, 若找不到会报错
  • 不会自动创建对象

@RequestAttribute

Jackson

依赖:

  1. <dependency>
  2. <groupId>com.fasterxml.jackson.core</groupId>
  3. <artifactId>jackson-databind</artifactId>
  4. <version>2.12.0</version>
  5. </dependency>

乱码

  1. <!--配置 解决json 乱码问题 使用了Jackson 就需要添加此配置-->
  2. <mvc:annotation-driven>
  3. <mvc:message-converters register-defaults="true">
  4. <bean class="org.springframework.http.converter.StringHttpMessageConverter">
  5. <constructor-arg value="UTF-8"/>
  6. </bean>
  7. <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  8. <property name="objectMapper">
  9. <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
  10. <property name="failOnEmptyBeans"/>
  11. </bean>
  12. </property>
  13. </bean>
  14. </mvc:message-converters>
  15. </mvc:annotation-driven>

对象 ——-> json

  1. ObjectMapper mapper = new ObjectMapper();
  2. Bean b = new Bean("qzw",3,6);
  3. String str = mapper.writeValueAsString(b);

json ———-> 对象

  1. ObjectMapper mapper = new ObjectMapper();
  2. Bean str = mapper.readValue(Jstr,Bean.class);
  • fastjson 与这个类似