Spring MVC

1 Spring MVC 概览

Spring 提供了一个功能齐全的 MVC 框架用于构建 Web 应用程序。Spring 框架可以很容易的和其他的 MVC 框架融合(如 Struts),该框架使用控制反转(IOC)将控制器逻辑和业务对象分离开来。它也允许以声明的方式绑定请求参数到业务对象上。

  • DispatcherServlet
    • Spring 的 MVC 框架是围绕 DispatcherServlet 来设计的,它用来处理所有的 HTTP 请求和响应。
  • WebApplicationContext
    • WebApplicationContext 继承了 ApplicationContext,并添加了一些 web 应用程序需要的功能。和普通的 ApplicationContext 不同,WebApplicationContext 可以用来处理主题样式,它也知道如何找到相应的 servlet。
  • Controller
    • 控制器提供对应用程序行为的访问,通常通过服务接口实现。控制器解析用户的输入,并将其转换为一个由视图呈现给用户的模型。Spring 通过一种极其抽象的方式实现控制器,它允许用户创建多种类型的控制器。
    • @Controller 注解表示该类扮演控制器的角色。Spring 不需要继承任何控制器基类或应用 Servlet API。
  • @RequestMapping 注解用于将 URL 映射到任何一个类或者一个特定的处理方法上。

1.1 Spring MVC 运行原理

img

  1. Spring MVC 通过一个单独的前端控制器(DispatcherServlet)过滤分发请求。
  2. DispatcherServlet 根据处理器映射(HandlerMapping)和请求携带的 URL 决定将请求发送给某个控制器(Controller)。
  3. 控制器从请求中取得信息,然后委托业务逻辑组件处理。将处理结果打包在模型(model)中,然后指定一个视图(view)的逻辑名称,然后将请求和模型、视图名称一起发送回 DispatcherServlet。
  4. DispatcherServlet 用视图名称查找对应的视图解析器(ViewResolver),负责将逻辑名称转换成对应的页面实现。
  5. 最后一步就是视图的实现。视图会使用模型数据填充到视图实现中,然后将结果放在 HTTP 响应对象中。

1.2 Spring MVC 配置

1)配置前端控制器

继承了 AbstractAnnotationConfigDispatcherServletInitializer,会在项目运行初始化被自动发现并加载。

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// 根容器
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
// Spring mvc 容器,指定配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
// DispatcherServlet 映射,从"/"开始
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}

AppInitializer 类需要实现三个方法,RootConfig 和 WebConfig 是两个关键配置类,而 getServletMappings 只需要返回一个 String 的列表,{“/”}的意思是监听访问 url 下所有的请求。

2)配置视图解析器

@EnableWebMvc:启动 Spring MVC 特性
configer.enable():静态资源的请求将转交给 servlert 容器的 default servlet 处理。

  • setPrefix() 方法用于设置视图路径的前缀;
  • setSuffix() 用于设置视图路径的后缀;
  • setExposeContextBeansAsAttributes(true) 使得可以在 JSP 页面中通过 ${ } 访问容器中的 bean
@Configuration
@EnableWebMvc//启动Spring MVC
@ComponentScan("org.test.spittr.web")//启动组件扫描
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver() {
// 配置JSP视图解析器
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
// 可以在JSP页面中通过${}访问beans
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); //配置静态文件处理
}
}
3)配置 Bean

RootConfig 在设置扫描机制的时候,将之前 WebConfig 设置过的那个包排除了。

@Configuration
@ComponentScan(basePackages = { "org.test.spittr.controller" }, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
public class RootConfig {
}

2 编写 Controller

2.1 控制器类

控制器类就是含有被 @RequestMapping 注解修饰的方法的类。@Controller 是 @Component 的别名,返回一个视图逻辑名称。

@RequestMapping 可加在类上和方法上,可同时映射多个路径

@Controller
@RequestMapping(value = "/")
public class HomeController {
@RequestMapping(value = { "/", "/homepage" }, method = RequestMethod.GET)
public String home() {
return "home";
}
}

2.2 请求参数

Spring MVC 提供了三种方式,可以让客户端给控制器的 handler 传入参数:

1)查询参数

@RequestParam,可设默认和非必填

@RequestMapping(method = RequestMethod.GET)
public List<Spittle> spittles(@RequestParam("max") long max,
@RequestParam(value = "count", defaultValue = "20") int count) {
return spittleRepository.findSpittles(max, count);
}
2)表单参数
  • “redirect:”前缀:解析为重定向的规则, 而不是视图的名称。
  • “forward:”前缀:请求将会前往(forward) 指定的 URL 路径, 而不再是重定向。
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String processRegistration(Spitter spitter) {
return "redirect:/spitter/" + spitter.getUsername();
}
3)路径参数

@PathVariable,如果函数参数和占位符名称相同,可省略注解的参数

@RequestMapping(value = "abc/{spittleId}", method = RequestMethod.GET)
public String showSpittle(@PathVariable("spittleId") long spittleId,Model model) {
}

2.3 校验参数

Java Validation API 定义了多个注解, 这些注解可以放到属性上,从而限制这些属性的值。

注 解 描 述
@AssertFalse 所注解的元素必须是 Boolean 类型, 并且值为 false
@AssertTrue 所注解的元素必须是 Boolean 类型, 并且值为 true
@DecimalMax 所注解的元素必须是数字, 并且它的值要小于或等于给定的 BigDecimalString 值
@DecimalMin 所注解的元素必须是数字, 并且它的值要大于或等于给定的 BigDecimalString 值
@Digits 所注解的元素必须是数字, 并且它的值必须有指定的位数
@Future 所注解的元素的值必须是一个将来的日期
@Max 所注解的元素必须是数字, 并且它的值要小于或等于给定的值
@Min 所注解的元素必须是数字, 并且它的值要大于或等于给定的值
@NotNull 所注解元素的值必须不能为 null
@Null 所注解元素的值必须为 null
@Past 所注解的元素的值必须是一个已过去的日期
@Pattern 所注解的元素的值必须匹配给定的正则表达式
@Size 所注解的元素的值必须是 String、 集合或数组, 并且它的长度要符合给定的范围
校验 bean 对象

@Valid 注解标注要检验的参数,Errors 参数要紧跟其后面

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String processRegistration(@Valid Spitter spitter, Errors errors) {
if(errors.hasErrors()){
...
}
return "redirect:/spitter/" + spitter.getUsername();
}

2.4 其他注解

  • @RequestBody:将方法参数直接绑定到 HTTP 请求 Body 上
  • @ResponseBody:将返回值作为响应体
  • @RestController:避免重复写 @ResponseBody
  • @CookieValue
  • @RequestHeader

Spring 4.3 中引进了{@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping} 来帮助简化常用的 HTTP 方法的映射 并更好地表达被注解方法的语义

  • @GetMapping 是一个组合注解:是 @RequestMapping(method = RequestMethod.GET) 的缩写
  • @PostMapping 是一个组合注解:是 @RequestMapping(method = RequestMethod.POST) 的缩写
Author: iMine
Link: https://imine141.github.io/2020/07/22/Spring/Web/Spring%20MVC/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.