Spring MVC

Spring MVC

原理

Spring MVC_第1张图片

搭建Spring MVC

  1. 配置DispatcherServlet

    1. java 配置(要求Servelt版本是3.0)

      扩展AbstractAnnoattionConfigDisPatcherServletInitializer.

      原理:

      Servlet3.0可以使用实现ServletContainerInitializer接口的类,就会使用来配置servlet容器。

      其中Spring中SpringServletContainerInitializer实现了该接口。该实现使用实现WebApplicationInitializer的类进行配置。

      而AbstractAnnotationConfigDispatcherServletInitializer实现了WebApplicationInitializer接口。

      具体内容:

      AbstractAnnoattionConfigDisPatcherServletInitializer的实现重写三个方法。

      1. 第一个方法是getServletMappings()
      2. 会创建DispatcherServlet和ContextLoaderListener.

        1. getServletConfigClasses()方法将会加载Web组件,比如控制器,视图解析器和处理器映射
        2. getRootConfigClasses()方法会加载中间层和数据层的组件

启用Spring MVC

  1. Java配置

    @Configuration
    @EnableWebMvc //启用Spring MVC
    @ComponentScan("backpages") //启用组件扫描
    public class WebConfig extends WebMvcConfigurerAdapter{
        
        @Bean            //配置jsp视图解析器
        publci ViewResolver viewResolver(){
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix("/WEB-INF/views");
            resolver.setSuffix(".jsp");
            return resolver;
        }
    }
    
    
    @Configuration
    @ComponentScan(basePackages={"spitter"})
    public class RootConfig{}

编写控制器

  1. 基础

    @Controller  //基于@Component作为组件扫描
    @RequestMapping("/") //URL映射
    public class HomeController{
        
        @RequestMapping("/home")
        public String home(){
            return "home"; //返回逻辑视图名
        }
    }
  2. 传递模型数据到视图中

    
    @Controller  //基于@Component作为组件扫描
    @RequestMapping("/") //URL映射
    public class HomeController{
        
        @RequestMapping("/home")
        public String home(Model model){
            String name = "name";
            model.addAttribute("name", name);
            return "home"; //返回逻辑视图名
        }
    }
    
    @Controller  //基于@Component作为组件扫描
    @RequestMapping("/") //URL映射
    public class HomeController{
        
        @RequestMapping("/home")
        public String home(Map model){
            String name = "name";
            model.put("name", name);
            return "home"; //返回逻辑视图名
        }
    }
    
    
    @Controller  //基于@Component作为组件扫描
    @RequestMapping("/") //URL映射
    public class HomeController{
        
        @RequestMapping("/home")
        public List spittles(Map model){
            return new ArrayList();   //返回视图根据请求路径推断出
        }
    }  
  3. 接受请求参数

    //1. 查询数据
    @RequestMapping("/home")
    public String home(
        @RequestParam(value = "count" ,requires = false, defaultValue="20") int count){
            String name = "name";
            model.put("name", name);
            return "home"; //返回逻辑视图名
    }
    // 2. 路径数据
    @RequestMapping("/{spittleId}")
    public String home(
        @PathVariable(value = "spittleId" ,requires = false, defaultValue="20") int count){
            String name = "name";
            model.put("name", name);
            return "home"; //返回逻辑视图名
    }
    //3.表单数据
    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            model.put("name", name);
            return "redirect:/spitter" + user.getUsetName();
    }
    
    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            model.put("name", name);
            return "include:/spitter" + user.getUsetName();
    }
  4. 校验表单
注解 描述
@AssertFalse 所注解的元素必须是Boolean类型,并且值为false
@AssertTrue 所注解的元素必须是Boolean类型,并且值为true
@Max 所注解的元素必须是数字,并且它的值要小于或等于给定的值
@Min 所注解的元素必须是数字,并且它的值要大于或等于给定的值
@NotNull 所注解的元素不能为null
@Size 所注解的元素的值必须是String,集合或者数组,并且它的长度要符合给定的范围

示例:

@RequestMapping("/{spittleId}")
public String home(
    @Valid User user,
    Errors errors
){
    
    if (errors.hasErrors()){  //校验不会阻止表单提交需要处理
    return "redgisterFomr";
    }
    
        String name = "name";
        model.put("name", name);
        return "include:/spitter" + user.getUsetName();
}


public class User{
    
    @NotNull
    @Size(min=2, max=30)
    private String name;
   
}

配置视图解析器

  1. Thymeleaf

    @Bean            //Thymeleaf视图解析器
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
    
    @Bean    //模板引擎
    public TemplateEngine templateEngine(TemplateResolver templateResolver){
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTEmplateResovler(templateResolver);
        return templateEngine;
    }
    
    @Bean    //模板解析器
    public TemplateResolver templateResolver(){
        TemplateResolver templateResover = new ServletContextTemplateResovler();
        templateResover.setPrefix("/WEB-INF/templates");
        templateResover.setSuffix(".html");
        templateResover.setTemplateMode("HTML5");
        return templateResover;
    }

处理异常

如果程序出现异常,那么返回给用户的还是一个响应,必须将异常转换为响应

spring自身的一些异常转换为状态码

  1. 将Spring自身的异常转换为状态码

    Spring异常 HTTP状态码
    BindException 400
    ConversionNotSupportedException 500
    HttpMediaTypeNotAcceptableException 406
    HttpMessageNotReadableException 400
    ... ...
  2. 将程序自身的异常转换为状态码

    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            if (user == null){
            throw new SpittleNotFoundException();
            }
            model.put("name", name);
            return "redirect:/spitter" + user.getUsetName();
    }
    
    //转换为状态码404
    @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found")
    public class SpittleNotFoundException extends RuntimeException{}
  3. 编写异常处理方法

    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            if (user == null){
            throw new SpittleNotFoundException();
            }
            model.put("name", name);
            return "redirect:/spitter" + user.getUsetName();
    }
    
    //该方法可以处理同一个控制器里面的所有该SpittleNotFoundException异常的处理方法
    @ExceptionHandler(DuplicateSpittleException.class)
    public String SpittleNotFoundException(){
        return "error/duplicate";
    }

为控制器添加通知

使用@ControllerAdvice注解里面的方法都给每一个控制器带有@RequestMapping注解的方法运行,一般@ControllerAdvice注解有一下几个注解配合使用:

  1. @ExceptionHandler
  2. @InitBinder
  3. @ModelAttribute

    @ControllerAdvice
    publci class AppwideExceptionHandler{
        
        @ExceptionHandler(DuplicateSpittleException.class)
        public String duplicateSpittleHandler(){
            return "error/duplicate";
        }
        
       @InitBinder
      public void initBinder(WebDataBinder binder) {
        StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
        binder.registerCustomEditor(String.class, stringtrimmer);
      }
        
      @ModelAttribute("currentURI")
      public String getCurrentURI(HttpServletRequest request) {
        return RequestUtils.getUriTrimContextPath(request);
      }
    
    }

跨重定向请求传递数据

我们知道重定向的数据不会保留原始请求的数据,那么我们如何把原始请求的数据一起带过去呢?

  1. 使用URL用路径变量或者查询参数的形式

    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            model.put("name", name);
            return "redirect:/spitter" + user.getUsetName();
    }
    
    @RequestMapping("/{spittleId}")
    public String home(
        User user){
            String name = "name";
            model.put("name", name);
            return "redirect:/spitter/{name}";
    }
  2. 使用flash属性

    但是当我们的数据很多的时候,比如是一个对象的时候,这样就很麻烦了,我们想想是不是可以把数据放在session里面,这样我们就可以共享数据了,然后在请求完成之后把数据给去除,spring觉得这部分去除的工作不需要开发关心,所以做了一个flash属性,实现该功能。使用RedirectAttributes,RedirectAttributes拥有Model的全部功能。

    @RequestMapping("/{spittleId}")
    public String home(
        User user,
        RedirectAttributes model){
            String name = "name";
            model.addFlashAttribute("user", user);
            return "redirect:/spitter/{name}";
    }

你可能感兴趣的:(spring-mvc)