作者:耿世述_511 | 来源:互联网 | 2023-06-04 20:51
1.请求映射1.1 rest 请求Rest风格支持(使用HTTP请求方式动词来表示对资源的操以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /save
1.请求映射 1.1 rest 请求 Rest风格支持(使用HTTP请求方式动词来表示对资源的操以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户 核心Filter;HiddenHttpMethodFilter 用法: ①表单method=post,隐藏域 _method=put ,②SpringBoot中手动开启 @xxxMapping 1.2 rest 请求原理 表单提交会带上_method=PUT 请求过来被HiddenHttpMethodFilter拦截请求是否正常,并且是POST获取到_method的值 兼容以下请求;PUT.DELETE.PATCH 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。 @Bean @ConditionalOnMissingBean ( HiddenHttpMethodFilter. class ) @ConditionalOnProperty ( prefix = "spring.mvc.hiddenmethod.filter" , name = "enabled" , matchIfMissing = false ) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter ( ) { return new OrderedHiddenHttpMethodFilter ( ) ; }
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class) 从这里我们可以知道只要我们自己配置了bean,那么就用我们自己的
@ConditionalOnProperty(prefix = “spring.mvc.hiddenmethod.filter”, name = “enabled”, matchIfMissing = false) 从这我们可以知道默认这个过滤器是不开启的,要开启的话需要我们手动开启
进入HiddenHttpMethodFilter类
protected void doFilterInternal ( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest requestToUse = request; if ( "POST" . equals ( request. getMethod ( ) ) && request. getAttribute ( "javax.servlet.error.exception" ) == null) { String paramValue = request. getParameter ( this . methodParam) ; if ( StringUtils. hasLength ( paramValue) ) { String method = paramValue. toUpperCase ( Locale. ENGLISH) ; if ( ALLOWED_METHODS. contains ( method) ) { requestToUse = new HiddenHttpMethodFilter. HttpMethodRequestWrapper ( request, method) ; } } } filterChain. doFilter ( ( ServletRequest) requestToUse, response) ; }
1.3 rest使用客户端工具如postman 则无需使用filter 2.请求映射原理 先回顾下SpringMvc的原理图 SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet------> doDispatch()
protected void doDispatch ( HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false ; WebAsyncManager asyncManager = WebAsyncUtils. getAsyncManager ( request) ; try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart ( request) ; multipartRequestParsed = ( processedRequest != request) ; mappedHandler = getHandler ( processedRequest) ;
RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。
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; }
SpringBoot自动配置欢迎页WelcomePageHandlerMapping 。访问 /能访问到index.html;
SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
如果有就找到这个请求对应的handler 如果没有就是下一个 HandlerMapping
我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping
3.请求处理—常用的参数注解 @PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@COOKIEValue、@RequestBody @RequestAttribute
@RestController public class ParameterTestController { @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 ( "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; } @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; } @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; } }
关于SpringBootMVC 功能 自定义 如果你想定制化一些功能,只需要写这个组件,然后把他交给SpringBoot,他会自动帮我们装配。
在springMVC中有许多xxxConfiguration 配置类,这个就要注意了,帮助我们进行了扩展配置
①If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. 不用@EnableWebMvc注解。使用 @Configuration + WebMvcConfigurer 自定义规则
②If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components. 声明 WebMvcRegistrations 改变默认底层组件
③If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc. 使用 @EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC
自定义SpringMVC的功能