1 Spring MVC

Wu Jun 2020-01-10 11:11:30
06 Spring > 04 Web

1 Spring MVC 概览

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

1.1 Spring MVC 运行原理

  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 处理。

@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)表单参数
@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 其他注解

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