一.SpringMVC基本原理

1.基本概念

SpringMVC框架是围绕前端控制器DispatcherServlet这个类为核心运转的。DispatcherServlet最主要的功能就是拦截来自用户的请求,并将其分配给相应的类(这样的类被称为Handler)处理,并将处理结果返回给用户。

2.执行的详细流程:

(1)用户发送请求,被DispatcherServlet截取,准备分配

(2)DispatcherServlet对请求进行解析封装,调用HandlerMapping(处理器映射器) , 根据配置或者注解寻找所有相应的Handler类

(3)DispatcherServlet再将找到的类交给HandlerAdapter(处理器适配器),调用相应的处理方法来处理请求,返回处理器视图资源。

(4)DispatcherServlet将视图资源交由ViewResolver(视图解析器)处理解析,渲染视图,返回给客户。

非注解方式springmvc内嵌jetty springmvc注解的原理_java

3.三大基本组件 

(1)HandlerMapping(处理器映射器)

     HandlerMapping是请求映射处理器,其建立维护了请求与Controller的映射关系,也就是通过请求的url找到对应的逻辑处理单元(Controller),几种典型的HandlerMapping如下:

  • RequestMappingUrlHandlerMapping  发起请求后,RequestMappingUrlHandlerMapping匹配到RequestMapping注解中实际的url路径,从自身维护的map中根据url取出对应的方法,包装成HanderMethod对象,然后交给RequestMappinigHandlerAdapter,用于处理controller中实际的方法。即一个url映射到一个方法。
  • BeanNameUrlHandlerMapping : 需要在spring-mvc.xml中配置BeanNameUrlHandlerMapping以及bean对应的Controller。Controller要实现AbstractController,并通过bean将url映射到对应的Controller。即一个url映射到一个Controller对象,调用handleRequestInternal方法处理请求。
  • SimpleUrlHandlerMapping : 该类型的用法最灵活,既可以用于匹配静态资源、又可以简化controller等等。一般是通过直接查找url返回静态资源。

(2)HandlerAdapter (处理器适配器)

    按照特定规则(HandlerAdapter要求的规则)对处理器Handler进行执行,拿到后端控制器返回的结果ModelAndView后将结果返回给前端控制器DispatcherServlet。

(3)ViewResolver(视图解析器)

    主要负责将从DispatcherServlet中拿到的ModelAndView对象进行解析,生成View对象返回给DispatcherServlet。

二.SpringMVC 源码分析

SpringMVC组件原理分析详见

三.SpringMVC常用注解

1.@PathVariable(路径变量)

        通过 @PathVariable 可以将访问路径URL 中的占位符参数绑定到控制器处理方法的入参中,占位符参数获取的方法有两种:

(1)使用@PathVariable("paramId") param 的方式依次绑定每个参数并取值。如果方法中的参数名与url中{}里面(占位符)的名字一样,则可以省略@PathVariable(“paramId”)中的paramId。

(2)使用@PathVariable Map<String,String>键值对的方式一次性获取所有的占位符参数值。

@RequestMapping("/user/{userId}/name/{username}",method = RequestMethod.GET) 
public String getUser(@PathVariable("userId") Integer userId,
                      @PathVariable("username") String username,
                      @PathVariable Map<String,String> pv){ 
  
    System.out.println("User Id : " + userId); 
    System.out.println("User name : " + username); 
    System.out.println("User : " + pv); 
  return "hello"; 

}

2.@RequestHeader(请求头信息)

        @RequestHeader注解用于将请求的头信息数据映射到功能处理方法的参数上。头信息获取的方法有两种:

(1)使用@RequestHeader("header-name") String param的方法获取请求头信息中相应的数据。

(2)使用@RequestHeader Map<String,String>的方法获取所有头信息的键值对集合。

@RequestMapping(“/header”) 
public String getHeader(@RequestHeader("User-Agent") String agent,
                        @RequestHeader Map<String,String> headers){ 
  
    System.out.println("User-Agent : " + agent); 
    System.out.println("Headers : " + headers); 
    return "success"; 

}

3.RequestParam(请求参数)

        @RequestParam主要用于将请求参数区域的数据映射到控制层方法的参数上,其使用语法如下:

语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=””) value:参数名 required:是否包含该参数,默认为true,表示该请求路径中必须包含该参数,如果不包含就报错。 defaultValue:默认参数值,如果设置了该值,required=true将失效,自动为false,如果没有传该参数,就使用默认值

        @RequestParam获取请求参数值的方式有两种,如下:

(1)使用@RequestParam("paramName") param 的方式依次绑定获取GET请求内的每个参数值。

(2)使用@RequestParam Map<String,String>MultiValueMap<String,String>键值对获取所有的请求参数。

//URL: http://localhost:8080/user?age=18&inters=basketball&inters=game

@GetMapping(“/user”) 
public String getUser(@RequestParam("age") Integer age,
                      @RequestParam("inters") List<String> inters,
                      @RequestParam MultiValueMap<String,String> params){ 
  
    System.out.println("User-Age : " + age); 
    System.out.println("User-Inters : " + inters); 
    System.out.println("User-Params : " + params); 
    return "success"; 

}

4.@RequestBody(获取请求体)

        @RequestBody是作用在形参列表上,用于将前端请求体中发送过来的数据(xml 格式或者 json等)通过HttpMessageConverter消息转换器封装到形参上。

@RequestMapping("/login")
//将前端请求体中的数据取出封装到content
public String login(@RequestBody String content){
   System.out.println(content);
   return "success";
}



@RequestMapping("/login")
//将前端JSON数据格式,通过消息转换器封装到Java Bean(要求属性名对应相同)
public ResultVo login(@RequestBody Users users, HttpSession session){
   ResultVo resultVo = userService.login(users,session);
   return resultVo;
}

注意:GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。

5. @ResponseBody

        @ResponseBody用于将Controller方法返回的对象数据,通过适当的HttpMessageConverter(转换器)转换为指定格式后,写入到Response对象的body数据区,一般在返回值不是某页面时使用,如返回json、xml等时使用。使用ResponseBody将会跳过视图处理的部分,直接返回数据(如我们前后端分离开发时,JSON数据的传输与处理)。

// 使用@ResponseBody注解进行标注,直接返回需要转换的对象
@ResponseBody
@RequestMapping("/login")
public ResultVo loginUser(@RequestBody User user) {
  ResultVo result = userService.login(user);
  return result;
}

注意:spring-mvc.xml配置文件中<mvc:annotation-driven  />开启之后,会给Spring容器初始化7个不同类型的数据格式转换器,每次请求SpringMVC会从List<HttpMessageConverter>中挑选一个来处理数据,遍历HttpMessageConverter集合,与数据获取可接受类型进行匹配。实际开发中,我们通常使用第三方的FastJson转换器来代替这七个成为默认转换器,解析和封装Json数据对象。