springboot01


springboot的学习周01

1.静态资源访问

  1. 静态资源访问前缀设置:(默认无前缀)

    spring:
      mvc:
        static-path-pattern: /res/**
  2. webjar
    自动映射 /webjars/**
    https://www.webjars.org/

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>3.5.1</version>
    </dependency>

访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径

2.请求参数处理

  • Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)

    • 以前:/getUser:获取用户 /deleteUser:删除用户 /editUser:修改用户 saveUser 保存用户
    • 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
  • 核心Filter:HiddenHttpMethodFilter

    • 用法: 表单method=post,隐藏域 _method=put
    • SpringBoot中手动开启
  • Rest原理(表单提交要使用REST的时候)

    • 表单提交会带上_method=PUT
    • 请求过来被HiddenHttpMethodFilter拦截
      • 请求是否正常,并且是POST
      • 获取到_method的值。
      • 兼容以下请求;PUT.DELETE.PATCH
      • 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
      • 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
  • Rest使用客户端工具:

    • 如PostMan直接发送Put、delete等方式请求,无需Filter;
    spring:
    mvc:
      hiddenmethod:
        filter:
          enabled: true   #开启页面表单的Rest功能

3.请求映射原理

  1. SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet-》doDispatch()
  2. RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
  3. 所有的请求映射都在HandlerMapping(HandlerMapping意思是处理器映射,把一个URL指定到一个Controller上)中:
    • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
    • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息:
      • 如果有就找到这个请求对应的handler
      • 如果没有就是下一个 HandlerMapping
 	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
	}
	return null;
}

4.普通参数和基本注解

  1. 注解:
    @PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

    @RestController
    public class ParameterTestController {
    
    
      //  car/2/owner/zhangsan
      @GetMapping("/car/{id}/owner/{username}")
      public Map<String,Object> getCar(@PathVariable("id") Integer id,
                                      @PathVariable("username") String name,
                                      @PathVariable Map<String,String> pv,
                                      @RequestHeader("User-Agent") String userAgent,
                                      @RequestHeader Map<String,String> header,
                                      @RequestParam("age") Integer age,
                                      @RequestParam("inters") List<String> inters,
                                      @RequestParam Map<String,String> params,
                                      @CookieValue("_ga") String _ga,
                                      @CookieValue("_ga") Cookie cookie){
             Map<String,Object> map = new HashMap<>();
    //        map.put("id",id);
    //        map.put("name",name);
    //        map.put("pv",pv);
    //        map.put("userAgent",userAgent);
    //        map.put("headers",header);
              map.put("age",age);
              map.put("inters",inters);
              map.put("params",params);
              map.put("_ga",_ga);
              System.out.println(cookie.getName()+"===>"+cookie.getValue());
              return map;
        }
        @PostMapping("/save")
        public Map postMethod(@RequestBody String content){
            Map<String,Object> map = new HashMap<>();
            map.put("content",content);
            return map;
        }
        //1、语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd
        //2、SpringBoot默认是禁用了矩阵变量的功能
        //      手动开启:原理。对于路径的处理。UrlPathHelper进行解析。
        //              removeSemicolonContent(移除分号内容)支持矩阵变量的
        //3、矩阵变量必须有url路径变量才能被解析
        @GetMapping("/cars/{path}")
        public Map carsSell(@MatrixVariable("low") Integer low,
                            @MatrixVariable("brand") List<String> brand,
                            @PathVariable("path") String path){
            Map<String,Object> map = new HashMap<>();
            map.put("low",low);
            map.put("brand",brand);
            map.put("path",path);
            return map;
        }
        // /boss/1;age=20/2;age=10
        @GetMapping("/boss/{bossId}/{empId}")
        public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                        @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
            Map<String,Object> map = new HashMap<>();
            map.put("bossAge",bossAge);
            map.put("empAge",empAge);
            return map;
        }
    }
  2. 复杂参数:

    • Map、Model(map、model里面的数据会被放在request的请求域中 相当于request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

    • map和model是一个对象 mavContainer 因为id都一样 都是5845,底层都是调用mavContainer.getModel()获取到参数(map,model)的值

    • 当拿到参数值之后,又是怎么样把参数放到response域对象中的呢:在 ServletInvocableHandlerMethod.java中有一个方法处理返回值,将mavContainer一起进行处理,进去后发现先找到返回值的处理器进行处理,返回值如果是一个字符串,那就保存到mavContainer的view(视图地址)里面,然后数据封装到defaultModel里面。

    • 最后将model的数据保存到request域里面

      protected void exposeModelAsRequestAttributes(Map<String, Object> model,
          HttpServletRequest request) throws Exception {
      
        model.forEach((name, value) -> {
          if (value != null) {
            request.setAttribute(name, value);
          }
          else {
            request.removeAttribute(name);
          }
        });
      }
      this.returnValueHandlers.handleReturnValue(
            returnValue, getReturnValueType(returnValue), mavContainer, webRequest);//
      @GetMapping("/params")
      public String testParam(Map<String,Object> map,
                              Model model,
                              HttpServletRequest request,
                              HttpServletResponse response){
          map.put("hello","world666");
          model.addAttribute("world","hello666");
          request.setAttribute("message","HelloWorld");
      
          Cookie cookie = new Cookie("c1","v1");
          response.addCookie(cookie);
          return "forward:/success";
      }
      
      
      @ResponseBody
      @GetMapping("/success")
      public Map success(@RequestAttribute(value = "msg",required = false) String msg,
                        @RequestAttribute(value = "code",required = false)Integer code,
                        HttpServletRequest request){
          Object msg1 = request.getAttribute("msg");
      
          Map<String,Object> map = new HashMap<>();
          Object hello = request.getAttribute("hello");
          Object world = request.getAttribute("world");
          Object message = request.getAttribute("message");
      
          map.put("reqMethod_msg",msg1);
          map.put("annotation_msg",msg);
          map.put("hello",hello);
          map.put("world",world);
          map.put("message",message);
      
          return map;
      
      }
      
    • 关于@ResponseBody注解请参照另外一篇博客@ResponseBody

5.POJO的封装

  1. 自定义类型的参数是由ServletModelAttributeMethodProcessor进行解析

    @Nullable
      private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
        HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
        if (result == null) {
          for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
            if (resolver.supportsParameter(parameter)) {  //如果解析器支持自定义类型的参数就返回true
              result = resolver;                          //自定义类型的参数用ServletModelAttributeMethodProcessor进行解析
              this.argumentResolverCache.put(parameter, result);
              break;
            }
          }
        }
        return result;
      }
    
  2. 然后获得参数类型,创建一个空的自定义参数对象(Person对象),接下来将原生的request请求(webRequest)和空的Person对象(attribute)封装到WebDataBinder里面,WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。利用反射封装到JavaBean中

  3. 我们可以给WebDataBinder里面放自己的Converter

    //1、WebMvcConfigurer定制化SpringMVC的功能
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 不移除;后面的内容。矩阵变量功能就可以生效
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
    
            @Override
            public void addFormatters(FormatterRegistry registry) {
                registry.addConverter(new Converter<String, Pet>() {
    
                    @Override
                    public Pet convert(String source) {
                        // 啊猫,3
                        if(!StringUtils.isEmpty(source)){
                            Pet pet = new Pet();
                            String[] split = source.split(",");
                            pet.setName(split[0]);
                            pet.setAge(Integer.parseInt(split[1]));
                            return pet;
                        }
                        return null;
                    }
                });
            }
        };
    }

文章作者: RD
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 RD !
评论
评论
  目录