1、SpringMVC自动配置概览

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)

The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • 内容协商视图解析器和BeanName视图解析器
  • Support for serving static resources, including support for WebJars (covered later in this document)).

    • 静态资源(包括webjars)
  • Automatic registration of Converter, GenericConverter, and Formatter beans.

    • 自动注册 Converter,GenericConverter,Formatter
  • Support for HttpMessageConverters (covered later in this document).

    • 支持 HttpMessageConverters (后来我们配合内容协商理解原理)
  • Automatic registration of MessageCodesResolver (covered later in this document).

    • 自动注册 MessageCodesResolver (国际化用)
  • Static index.html support.

    • 静态index.html 页支持
  • Custom Favicon support (covered later in this document).

    • 自定义 Favicon
  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

    • 自动使用 ConfigurableWebBindingInitializer ,(DataBinder负责将请求数据绑定到JavaBean上)

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

2、简单功能分析

2.1、静态资源访问

1、静态资源目录

只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources

访问 : 当前项目根路径/ + 静态资源名

静态资源访问或者其他资源访问的原理:

请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

2、静态资源访问前缀和静态资源目录

默认无前缀: **/****.

我们可如下配置static-path-pattern修改其前缀:

spring:mvc:static-path-pattern: /res/**

访问路径:当前项目 + static-path-pattern + 静态资源名 => 静态资源文件夹下找静态资源

我们可通过static-locations改变默认的静态资源路径(目录)

spring:resources:static-locations: [classpath:/haha/]

这样我们访问静态资源将从 resources/haha/ 下进行查找.

3、webjar

SpringBoot 中将一些静态资源达成了Jar包,通过导入依赖,我们可以使用相关的静态资源.

自动映射 /webjars/**

可通过https://www.webjars.org/选取需要的静态资源jar包.

举例:

        <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.2、欢迎页支持

  • 静态资源路径下 index.html

可以配置静态资源路径,但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致welcome page功能失效resources:static-locations: [classpath:/haha/]
  • controller能处理/index

2.3、自定义 Favicon

favicon.ico 放在静态资源目录下即可。

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

Ctrl+shift+r/Ctrl+F5:强制刷新页面

2.4、静态资源配置原理

  • SpringBoot启动默认加载 xxxAutoConfiguration 类(自动配置类)
  • SpringMVC功能的自动配置类 WebMvcAutoConfiguration,生效
@Configuration(proxyBeanMethods = false
)
@ConditionalOnWebApplication(type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}
  • 给容器中配了什么。
 @Configuration(proxyBeanMethods = false)@Import(EnableWebMvcConfiguration.class)@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })@Order(0)public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
  • 配置文件的相关属性和xxx进行了绑定。WebMvcProperties==spring.mvc、ResourceProperties==spring.resources

1、配置类只有一个有参构造器

//有参构造器所有参数的值都会从容器中确定
//ResourceProperties resourceProperties;获取和spring.resources绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========
//DispatcherServletPath
//ServletRegistrationBean   给应用注册Servlet、Filter....public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,ObjectProvider<DispatcherServletPath> dispatcherServletPath,ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {this.resourceProperties = resourceProperties;this.mvcProperties = mvcProperties;this.beanFactory = beanFactory;this.messageConvertersProvider = messageConvertersProvider;this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();this.dispatcherServletPath = dispatcherServletPath;this.servletRegistrations = servletRegistrations;}

2、资源处理的默认规则

#########################addResourceHandlers()方法#################################
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {//判断是否禁用静态资源logger.debug("Default resource handling disabled");//如果禁用则到此结束.return;}Duration cachePeriod = this.resourceProperties.getCache().getPeriod();CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();//访问webjars的规则if (!registry.hasMappingForPattern("/webjars/**")) {//如果是,则从/META-INF/resources/webjars/进行寻找静态资源.customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));//按照设置的时间缓存} //其他静态资源的规则String staticPathPattern = this.mvcProperties.getStaticPathPattern();//获取获取静态资源路径static-path-pattern的值.if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));}//调用getResourceLocations(),从staticLocations下找静态资源}#########################################################################################
spring:resources:add-mappings: false   false:禁用所有静态资源规则cache:1100             静态资源可以存活多长时间   @ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/","classpath:/resources/", "classpath:/static/", "classpath:/public/" };private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;...
}

3、欢迎页的处理规则

 //HandlerMapping:处理器映射。保存了每一个Handler能处理哪些请求。 @Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),this.mvcProperties.getStaticPathPattern());welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());return welcomePageHandlerMapping;}
#######################WelcomePageHandlerMapping()构造方法.#############################WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {//如果欢迎页存在,并且staticPathPattern是默认的,则进行转发.if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {//要用欢迎页功能,必须是/**logger.info("Adding welcome page: " + welcomePage.get());setRootViewName("forward:index.html");}else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {// 否则调用Controller,看谁能处理,就作为一个欢迎页.  /indexlogger.info("Adding welcome page template: index");setRootViewName("index");  }}

4、favicon

如果并且staticPathPattern是默认的/**,则取资源路径下寻找favicon.jpg,如果有则使用.如果不是默认的配置,则该规则失效.

3、请求参数处理

0、请求映射

1、rest使用与原理

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

    • 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
    • 现在: /user GET- 获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
    • 核心Filter:HiddenHttpMethodFilter
    • 用法: 表单method=post ,隐藏域 _method=put
    • SpringBoot中手动开启:spring.mvc.formcontent.filter.enable=true
 #####################################MethodController################################## @RestController
public class MethodController {@RequestMapping(value = "/user",method = RequestMethod.GET)public String getUser(){return "GET-张三";}@RequestMapping(value = "/user",method = RequestMethod.POST)public String saveUser(){return "POST-张三";}@RequestMapping(value = "/user",method = RequestMethod.PUT)public String putUser(){return "PUT-张三";}@RequestMapping(value = "/user",method = RequestMethod.DELETE)public String deleteUser(){return "DELETE-张三";}
}#######################################yaml配置###########################################
spring:mvc:hiddenmethod:filter:enabled: true   #开启页面表单的Rest功能

Rest原理(表单提交要使用REST的时候)

  • 表单提交会带上**_method=PUT**

  • 请求过来被HiddenHttpMethodFilter拦截

    • 请求是否正常,并且是POST
    • 获取到**_method**的值。
    • 兼容以下请求;PUT.DELETE.PATCH
    • 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值。
    • 过滤器链放行的时候用wrapper(被包装后的request)。以后的方法调用getMethod是调用 requestWrapper的。
###############################原理#####################################################
################SpringMvcAutoConfiguration############################################# @Bean@ConditionalOnMissingBean(FormContentFilter.class)//OrderedFormContentFilter继承FormContentFilter    没有FormContentFilter 就创建一个.@ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true)public OrderedFormContentFilter formContentFilter() {return new OrderedFormContentFilter();}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {HttpServletRequest requestToUse = request;
//判断类型是否为post类型if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {//获取_method的值.String paramValue = request.getParameter(this.methodParam);if (StringUtils.hasLength(paramValue)) {String method = paramValue.toUpperCase(Locale.ENGLISH);if (ALLOWED_METHODS.contains(method)) {requestToUse = new HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter(requestToUse, response);}

扩展:如何把_method 这个名字换成我们自己喜欢的。

@Configuration
public class WebConfig {//自定义Bean@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();//默认methodParam为_methodmethodFilter.setMethodParam("_m");//我们调用set方法,起名进行覆盖.return methodFilter;}
}

Rest使用客户端工具

  • 如PostMan/IDEA-Client直接发送Put、delete等方式请求,无需Filter。

注:我们还可以使用@PostMapping,@DeleteMapping,@PutMapping直接发送对应的注解.

2、请求映射原理

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);// 找到当前请求使用哪个Handler(Controller的方法)处理mappedHandler = getHandler(processedRequest);//HandlerMapping:处理器映射。/xxx->>xxxx}...}               ##########################################getHandler################################
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {//handlerMappings:处理器映射,一共五个.for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}

RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。

总结:

  • 所有的请求映射都在HandlerMapping中。

  • SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;

  • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping

  • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。

    • 如果有就找到这个请求对应的handler
    • 如果没有就是下一个 HandlerMapping
  • 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping,即自定义 HandlerMapping

1、普通参数与基本注解

1.1、注解:

@PathVariable
  • 如果有参数,获取请求路径中参数的值.

  • 如果无参数,且后面跟 Map<String,String>类型的.将获取路径中所有参数的值并存放到该Map中.

@GetMapping("/car/{id}/owner/{username}")public Map<String,Object> getCar(@PathVariable("id") Integer id,@PathVariable("username") String name,@PathVariable Map<String,String> pv){Map <String, Object> map = new HashMap <>();map.put("id", id);map.put("name", name);map.put("pv", pv);return  map;}
##########################运行结果############################################{"pv":{"id":"3","username":"zhangsan"},"name":"zhangsan","id":3}
@RequestHeader
  • 如果有参数,获取的是指定请求头的值.
  • 无参数,且后跟类型为Map<String,String>,获取所有请求头的键和值.
@GetMapping("/car")public Map<String,Object> getCar(@RequestHeader("User-Agent") String userAgent,@RequestHeader Map<String,String> headers){Map <String, Object> map = new HashMap <>();map.put("userAgent", userAgent);map.put("headers", headers);return  map;}
@RequestParam
@GetMapping("/car")public Map<String,Object> getCar(@RequestParam("age") Integer age, @RequestParam("inters") List<String> inters,@RequestParam Map<String,String> params){Map <String, String> map = new HashMap <>();map.put("age",age);map.put("inters", inters);map.put("params", params);return  map;}
##############################################################################{"inters":["football","game"],"params":{"age":"18","inters":"football"},"age":18}
@CookieValue
  • 如果有参数,获取的是指定Cookie的值.
  • 有参数,后面跟的是一个Cookie类型, 将Cookie值保存到另外一个Cookie中.
@RequestBody

获取Post请求的请求体.

@PostMapping("/save")public Map<String,Object> postMethod(@RequestBody String content){Map <String, Object> map = new HashMap <>();map.put("content", content);return map;}#################################################################################
{"content":"userName=zhagnsan&email=1456"}
@RequestAttribute
@Controller
public class RequestController {@GetMapping("/goto")public String goToPage(HttpServletRequest request){request.setAttribute("msg","成功了...");request.setAttribute("code",200);return "forward:/success"; //转发到success的请求}@ResponseBody@GetMapping("/success")public Map success(@RequestAttribute("msg")String msg,@RequestAttribute("code") Integer code,HttpServletRequest request){Map <String, Object> map = new HashMap <>();Object msg1 = request.getAttribute("msg");map.put("reqMathod_msg", msg1);map.put("anno_msg", msg);map.put("code", code);return map;}}
####################################################################################
{"reqMathod_msg":"成功了...","code":200,"anno_msg":"成功了..."}
@MatrixVariable

传统方式获取/cars/{path}?xxx=xxx&aaa=ccc queryString 中请求参数的数据使用@RequestParam

在页面开发,cookie禁用了,session里面的内容怎么使用?

未被禁用时:

  • 正向:每次请求时携带cookie,cookie中存放着jsessionid ,通过它这样可以找到指定的session.

  • 逆向**:session.set(a,b)—> jsessionid —> cookie ----> 每次发请求携带**。

    所以一旦cookie被禁用,session便无法找到了.

矩阵变量

5、SpringMVC自动配置概览相关推荐

  1. SpringMVC自动配置||如何修改SpringBoot的默认配置

    SpringMVC自动配置 1. Spring MVC auto-configuration Spring Boot 自动配置好了SpringMVC 以下是SpringBoot对SpringMVC的默 ...

  2. tns03505 无法解析名称_SpringBootWeb源码解析SpringMVC自动配置

    SpringMVC自动配置 在 Spring Boot 中引入了 spring-boot-starter-web 依赖,并完成了 DispatcherServlet 的自动配置之后,便会通过 WebM ...

  3. SpringBoot之SpringMVC自动配置

    关于SpringBoot中的SpringMVC自动配置的一些思考 : 自动配置 Spring Boot 自动配置好了SpringMVC 以下是SpringBoot对SpringMVC的默认配置:(We ...

  4. Spring Boot—SpringMVC自动配置原理以及扩展和全面接管SpringMVC

    文章目录 1.以下是SpringBoot对SpringMVC的默认配置 2.扩展SpringMVC 3.全面接管SpringMVC: 5.如何修改SpringBoot的默认配置 Spring MVC ...

  5. SpringBoot_web开发-SpringMVC自动配置原理

    我们自己分析Springboot的源码,里面有什么功能,第二个我们来参照官方文档,官方文档里面写了什么功能,我们看官方文档告诉我们自动配置了哪些,再来带大家来翻一翻源码,希望通过这一次的分析,后来的模 ...

  6. SpringMVC自动配置

    springboot为SpringMVC配置了自动配置,以下是SpringBoot对SpringMVC的默认配置 org.springframework.boot.autoconfigure.web. ...

  7. [SpringBoot2]web场景_SpringBoot2_SpringMVC自动配置概览

    Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我 ...

  8. java框架之SpringBoot(5)-SpringMVC的自动配置

    本篇文章内容详细可参考官方文档第 29 节. SpringMVC介绍 SpringBoot 非常适合 Web 应用程序开发.可以使用嵌入式 Tomcat,Jetty,Undertow 或 Netty ...

  9. springboot继承组件_SpringBoot如何扩展引入的组件,以及如何自动配置组件原理

    大家都知道,当我们创建SpringBoot项目之后,我们可以在pom文件下,引入我们想要启动的组件,当我们引入之后,SpringBoot会自动帮我们配置属性! 下面我们以SpringBoot引入Spr ...

最新文章

  1. 复制数据表的两种情况。
  2. python运行软件-Python中四种运行其他程序的方式
  3. 前端开发常用的Chrome插件推荐
  4. [SDOI2016]储能表
  5. Redis 数据库、键过期的实现
  6. php基础编程教程 pdf,手把手教你编程打印出PDF_PHP教程
  7. 学习 Shell —— 括号、引号
  8. SpringBoot @Condition 注解
  9. 惠康游戏手柄 WE-8400 Windows 10 驱动教程
  10. 对recv函数的一些理解
  11. web开发与设计,这些网站为你提供大量的开发资源与设计灵感
  12. Canvas实现龙卷风动态效果
  13. error: You must be logged in to the server (Unauthorized)
  14. Think in Java 4 中关于使用XOM操作xml文件
  15. 集成融云的视频通话功能
  16. c语言aps审核,APS考官最讨厌的几类人
  17. 读史鉴今:女人的12种结局
  18. 厦门市委书记走访图扑等多家软件企业调研元宇宙产业发展情况
  19. Unity 面积测量
  20. sqlserver-创建表

热门文章

  1. 时序分析基础(1)----寄存器时序分析模型
  2. Linux中如何添加自己的路径到PATH
  3. change charset of existed MySQL db
  4. [fpga基础]基础元器件
  5. OpenGL超级宝典第7版环境配置
  6. The Shawshank Redemption-5
  7. java - 锁粒度
  8. 组合数学_排列与组合
  9. Win10家庭版 误删winsock和winsock2注册表的解决方案
  10. zbb20180921 spring事物的七种事物传播属性行为及五种隔离级别