Spring之WebMvcConfigurationSupport
WebMvcConfigurationSupport是mvc的核心配置。开发spring,了解和掌握这个是必须的。
为了简约篇幅,本文把"WebMvcConfigurationSupport"缩写为wms。
本文主要关注围绕DispatcherServlet(分发者服务程序)发生的和wms有关的一些内容,不关注http请求在容器部分的机制和代码。
通过本文能够:
- 了解wms是做什么的
- 了解大体如何使用wms
- 作为了解和使用wms的一个简单参考
一、wms的介绍
1.原文注释
This is the main class providing the configuration behind the MVC Java config.
It is typically imported by adding @EnableWebMvc to anapplication @Configuration class.
An alternative more advanced option is to extend directly from this class and override methods as necessary,
remembering to add @Configuration to the subclass and @Bean to overridden @Bean methods.
For more details see the javadoc of @EnableWebMvc.
This class registers the following HandlerMappings:
•RequestMappingHandlerMapping ordered at 0 for mapping requests to annotated controller methods.
•HandlerMapping ordered at 1 to map URL paths directly to view names.
•BeanNameUrlHandlerMapping ordered at 2 to map URL paths to controller bean names.
•RouterFunctionMapping ordered at 3 to map router functions.
•HandlerMapping ordered at Integer.MAX_VALUE-1 to serve static resource requests.
•HandlerMapping ordered at Integer.MAX_VALUE to forward requests to the default servlet.
Registers these HandlerAdapters:
•RequestMappingHandlerAdapter for processing requests with annotated controller methods.
•HttpRequestHandlerAdapter for processing requests with HttpRequestHandlers.
•SimpleControllerHandlerAdapter for processing requests with interface-based Controllers.
•HandlerFunctionAdapter for processing requests with router functions.
Registers a HandlerExceptionResolverComposite with this chain ofexception resolvers:
•ExceptionHandlerExceptionResolver for handling exceptions through org.springframework.web.bind.annotation.ExceptionHandler methods.
•ResponseStatusExceptionResolver for exceptions annotated with org.springframework.web.bind.annotation.ResponseStatus.
•DefaultHandlerExceptionResolver for resolving known Springexception types
Registers an AntPathMatcher and a UrlPathHelperto be used by:
•the RequestMappingHandlerMapping,
•the HandlerMapping for ViewControllers
•and the HandlerMapping for serving resources
Note that those beans can be configured with a PathMatchConfigurer.
Both the RequestMappingHandlerAdapter and the ExceptionHandlerExceptionResolver are configured with default instances of the following by default:
•a ContentNegotiationManager
•a Default FormattingConversionService
•an org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean if a JSR-303 implementation is available on the classpath
•a range of HttpMessageConverters depending on the third-partylibraries available on the classpath.
我们翻译下:
wms是webMvc通过java代码方式配置的主类。
典型地,可以通过给一个应用的配置类(带@Configuration)添加@EnableWebMvc注解,即可导入Mvc java 配置。
另外一个更加高级的替代选项是继承本类,并根据需要重写一些方法,并记得为这个子类添加@Configuration注解,同时为那些重写@Bean方法添加@Bean注解。
更多的内容,请参考@EnableWebMvc的java文档
本类注册以下处理器映射:
.RequestMappingHandlerMapping(RequestMapping处理器映射) ,顺序为0,用于映射带注解的控制器方法
.HandlerMapping (处理器映射),顺序1,用于映射url路径和视图名称
.BeanNameUrlHandlerMapping(bean名称处理器映射),顺序2,用于映射url路径到控制器bean名称
.RouterFunctionMapping(路由器功能映射),顺序3,用于映射路由函数
.HandlerMapping (处理器映射),顺序Integer.MAX_VALUE-1,用于处理静态资源请求
.HandlerMapping (处理器映射),顺序Integer.MAX_VALUE,用于服务器内部重定向到一个默认的servlet
注册这些处理器适配器:
•RequestMappingHandlerAdapter(RequestMapping处理器适配器),用于处理到带注解的控制器方法请求
•HttpRequestHandlerAdapter(http请求处理器适配器),用于处理 带HttpRequestHanders的请求
•SimpleControllerHandlerAdapter(简单控制器处理器适配器),用于处理基于接口的控制的请求
•HandlerFunctionAdapter(处理器功能适配器),用于处理带路由器功能的请求
注册处理器异常解析复合器,该复合器带有一些异常处理器:
•ExceptionHandlerExceptionResolver(异常处理器异常解析器),用于处理org.springframework.web.bind.annotation.ExceptionHandler的异常
•ResponseStatusExceptionResolver(响应状态异常解析器),用于处理org.springframework.web.bind.annotation.ResponseStatus异常
•DefaultHandlerExceptionResolver(默认处理器异常解析器),用于处理已知的的spring异常类
注册一个antPathMatcher和一个urlPathHelper,以便能够被以下对象使用:
•RequestMappingHandlerMapping(RequestMapping处理器映射)
•HandlerMapping for ViewControllers ,用于视图控制器的处理器映射
•HandlerMapping for serving resources ,用于处理资源的处理器映射
注意,以上这些bean可以通过PathMatchCOnfigurer配置。
RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver都由以下对象的默认实例配置了:
.ContentNegotiationManager(媒体类型管理器,用于侦测请求的媒体类型)
.FormattingConversionService(格式转换服务)
.org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean(bean验证器,如果类路径具有JSR-303的实现)
.HttpMessageConverters(http消息转换器)。具体有几个转换器,需要看类路径的三方实现库的多寡
2.功能
如它的名称,即执行各种webMvc的配置,通过在其中定义大量的有关Bean(大约有25个左右),方便MVC的流程的特定环节从Bean工厂中获取这些bean,并利用这些Bean完成webMvc的大部分工作。
概括下,wms就是这些功能:
- 注册处理器映射,以便把请求导向具体的控制器、控制器方法、视图、资源。注意,这些映射器的目的是做一个关系匹配
- 注册处理器适配器,为具体的功能选择具体的处理程序。例如参数解析,消息转换等
- 注册异常处理器
- 注册路径映射解析有关类
总而言之,言而总之,wms就是告诉spring用于处理请求的有关工具,这些工具用于处理映射关系,解析参数,返回消息等等。
一个完整的web请求和响应过程中需要执行的动作所使用的配置(程序、配置)基本都可以在wms中进行管理,记住这一点基本上算是对wms有所了解了。
二、名词解析
需要记住和理解的名词非常多,只能挑本人关注的。
1.解释器/解决器
英文:Resolver
中文含义:问题解决者。 针对不同的场景,可以有很多的解释。在本文中,按照习惯,我们从用途进行翻译,大体翻译为解释器,转换器都可以。
2.拦截器
英文:interceptor
中文含义:进行拦截的人/物。在spring中,专门指拦截http请求的一段程序。和过滤器基本一样,没有什么本质上的区别。不过拦截器可以打断请求的过程,而过滤器主要做重定向(如果有必要)
3.控制器、参数、方法
控制器:controller,对应注解@Controller
参数:parameter,这里主要阐述的是控制器中方法的入参
方法:method,这里指控制器中的方法(有Request的方法)
我们日常spring编程主要针对这三者。
某种程度上,只要会复制粘贴+mvc你就可以说自己是一个java开发工程师了,是不是很容易啊?
4.返回值、消息
返回值:return value。控制器方法大部分情况下都有返回值,如果没有,那么spring也会给一个默认的响应
消息:message.这里指从客户端发送的请求消息或者是服务端返回给客户端的消息。这里我们主要关心ResponseBody注解。
5.Cors
英文:CORS(Cross-origin resource sharing)
中文:跨源资源共享
一般情况下,web服务器不允许跨源资源共享,但很多时候又有这个需求。所以需要指定什么资源可以被什么其它非同源请求访问。
6.资源和视图
资源:resource,spring通常指静态的数据(包括图片,脚本,文本,多媒体信息等等)
视图:view,spring指展示信息的页面
7.验证器
英文:validator,spring通常指用于校验特定参数的简单业务逻辑
8.格式化器和转换器
格式化器:formatter
转换器:converter
二者有相通之处,但基本一致,格式和转换基本即使你中有我,我中有你,密不可分。其作用,顾名思义,就是进行转化/格式化。 例如消息转换、属性转换等。
9.异常
具体略。
10.应用上下文和sevlet上下文
这两个太重要,因为WebMvcConfigurationSupport实现的很大一部分和应用上下文、服务器上下文有关。
- ApplicationContext:应用上下文,属于spring自有的一个应用上下文,主要管理spring的bean。能够管理bean,绝对是spring的最核心能力之一。
包路径:org.springframework.context.ApplicationContext
- ServletContext:服务器上下文,准确地说,通常地说,它指的是web服务器/容器的根上下文,容器通常为每个应用创建一个服务器上下文,保存应用和web相关的许多基本信息。
包路径:javax.servlet.ServletContext
我们开发的系统,某个方便面来说就是和两个东西关联:web+bean。web和bean有关的上下文就是 ServletContext,ApplicationContext。
11.媒体/媒介类型
英文:MediaType
包路径:org.springframework.http.MediaType
根据介绍,媒体/媒介类型实为MimeType的子类,spring仅仅对它做了一些包装,方便使用。
所以,根本上要理解MiME在http协议中的地位。
Mime的非常友好的介绍见这里:MIME 类型 - HTTP | MDN (mozilla.org)
或者看这里 MIME(多用途互联网邮件扩展类型)_百度百科 (baidu.com)
两个结合起来,就能够明白mime是什么东西。
如果有什么值得记的,就是为什么叫” mail extensions"(邮件扩展)。
邮件大概是互联网最早传递的数据信息,而且基本上是最重要的,所以开始命名的时候就这么叫了。但是现在iana(互联网号码分配机构)又慢慢要抛弃mime这个概念,改为mediaType(媒体类型)。
很明显这么称呼是更加合理的,如果没有什么特别说明,“媒体类型”就是表示MINE或者上下文类型(context-type)
12.请求映射处理器映射器(RequestMappingHandlerMapping)
注意这个前缀 RequestMapping(请求映射)本身是注解的名称(@RequestMapping)。
所以这个东西可以理解为RequestMapping注解的处理器映射器,大体作用是在注解和资源之间建立映射关系。
我们看下源码(默认的):
@Bean
@SuppressWarnings("deprecation")
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
mapping.setContentNegotiationManager(contentNegotiationManager);
mapping.setCorsConfigurations(getCorsConfigurations()); PathMatchConfigurer pathConfig = getPathMatchConfigurer();
if (pathConfig.getPatternParser() != null) {
mapping.setPatternParser(pathConfig.getPatternParser());
}
else {
mapping.setUrlPathHelper(pathConfig.getUrlPathHelperOrDefault());
mapping.setPathMatcher(pathConfig.getPathMatcherOrDefault()); Boolean useSuffixPatternMatch = pathConfig.isUseSuffixPatternMatch();
if (useSuffixPatternMatch != null) {
mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
}
Boolean useRegisteredSuffixPatternMatch = pathConfig.isUseRegisteredSuffixPatternMatch();
if (useRegisteredSuffixPatternMatch != null) {
mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
}
}
Boolean useTrailingSlashMatch = pathConfig.isUseTrailingSlashMatch();
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
if (pathConfig.getPathPrefixes() != null) {
mapping.setPathPrefixes(pathConfig.getPathPrefixes());
} return mapping;
}
这个代码核心是创建一个RequestMapping的处理器映射器,这个映射器又包含了什么东西了?
- 添加默认的转换器和资源url管理器的拦截器
- 添加请求媒体类型管理器
- 添加了跨域请求配置
- 添加了路径匹配器,以及路径有关的一些其它程序
13.请求映射处理器适配器(RequestMappingHandlerAdapter)
RequestMapping注解处理器适配器。
看源码(默认):
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setContentNegotiationManager(contentNegotiationManager);
adapter.setMessageConverters(getMessageConverters());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
adapter.setCustomArgumentResolvers(getArgumentResolvers());
adapter.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
if (configurer.getTaskExecutor() != null) {
adapter.setTaskExecutor(configurer.getTaskExecutor());
}
if (configurer.getTimeout() != null) {
adapter.setAsyncRequestTimeout(configurer.getTimeout());
}
adapter.setCallableInterceptors(configurer.getCallableInterceptors());
adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
return adapter;
}
- 设置媒体类型管理器(和映射器一样,都必须了解请求的媒体类型)
- 设置消息转换器
- web绑定初始化器(和转换服务、验证器有关)
- 设置自定义参数解释器
- 设置自定义返回值处理器
- 添加jackson请求体RequestBody顾问(如果有jackson类)
- 添加jackson响应体ResponseBody顾问(如果有jackson类)
- 配置异步任务执行器,设置异步请求超时。如果有配置异步
- 配置异步的可调用拦截器
- 配置异步延时结果拦截器
把这个内容和RequestMappingHanlderMapping的内容对照下,我们就更能够理解二者的区别。
--------------------------------------------------------------------------------------------------------------------
- 映射器:主管资源和路径有关的内容
- 适配器:主管具体请求消息处理和返回消息
注:spring已经提供了消息处理器的默认实现JackSon.
RequestMappingHandlerAdapter和RequestMappingHandleMapping是DispatcherServlet(分发器)的主要处理内容。
以下是分发器属性的主要内容:
/** MultipartResolver used by this servlet. */
@Nullable
private MultipartResolver multipartResolver; /** LocaleResolver used by this servlet. */
@Nullable
private LocaleResolver localeResolver; /** ThemeResolver used by this servlet. */
@Nullable
private ThemeResolver themeResolver; /** List of HandlerMappings used by this servlet. */
@Nullable
private List<HandlerMapping> handlerMappings; /** List of HandlerAdapters used by this servlet. */
@Nullable
private List<HandlerAdapter> handlerAdapters; /** List of HandlerExceptionResolvers used by this servlet. */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers; /** RequestToViewNameTranslator used by this servlet. */
@Nullable
private RequestToViewNameTranslator viewNameTranslator; /** FlashMapManager used by this servlet. */
@Nullable
private FlashMapManager flashMapManager; /** List of ViewResolvers used by this servlet. */
@Nullable
private List<ViewResolver> viewResolvers;
三、spring-mvc种http请求大概执行过程
这么多名词,其实本质上就是围绕http展开的,具体来说就是围绕spring的http实现来展开。
我们使用spring的主要目的就是为了web(http)应用。可以说,没有web,spring的存在的意义基本上就没有了。
利用ide提供的调试工具,最容易能够直观地了解一个http请求的大概执行过程。如果愿意,还可以详细到每一行代码。
下图是调试的时候,显示的调用链:
四、常用-配置拦截器
如何配置拦截器,这个没有什么太多可说。
记住一点,现在不但spring自身实现功能的时候使用了很多的拦截器(这个在springCloud中很明显),就是一般的开发人员也喜欢(滥)用大量的拦截器。
我们只能感激一点:现在电脑越来愉快了。
配置例子。
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 以下是启用 token认证的. 本例使用cookie认证的时候,请注释掉,避免无法完成测试
// 反过来,如果启用了token认证,那么过滤器验证就可以取消掉 ,或者取消 上文的 registrationBean()
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("*.js")
.excludePathPatterns("*.html").excludePathPatterns("*.css").excludePathPatterns("/login")
.excludePathPatterns("/logout").excludePathPatterns("/index").excludePathPatterns("/");
super.addInterceptors(registry);
}
五、常用-方法参数(输入)解析(请求)
spring已经有提供默认的以下几个注解的处理:@RequstBody,@RequestParam
但是当我们开发api的时候,常常有这样的需求:
- 在过滤器或者拦截器拦截请求并获取有关参数
- 在具体的控制方法中想获取请求的一些固定信息,例如登录用户信息,授权信息等等 。
5.1 例子-自定义参数注解
、 如果每个地方都写,有点麻烦,所以spring允许自定义的参数解析。
例子:
a.定义一个注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SessionAtrrAnnotation { }
b.继承并实现HandlerMethodArgumentResolver
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(SessionAtrrAnnotation.class);
} @Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return webRequest.getNativeRequest(HttpServletRequest.class).getSession().getAttribute("userInfo");
} }
c.在wms中注册
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginUserArgumentResolver());
} d.应用
@RequestMapping(value = "/deleteById")
@ResponseBody
public PublicReturn deleteById(@SessionAtrrAnnotation LoginUserInfo loginInfo) {
//TODO:删除用户
return null;
}
5.2 自定义特定数据类型解析
这种自定义类型,有两种情况:
a.解析非JSON媒体类型的参数
b.解析媒体类型为JSON的参数中某个属性
这个网络上有很多解决方案,例如:
SpringMVC自定义处理多种日期格式的格式转换器_二木成林的博客-CSDN博客_springmvc日期转换 -- 这个是解析非json媒体类型参数的
不过作者是比较传统的xml配置,如果是springboot,直接在wms中覆盖addFormatters即可。
fastjson序列化时间自定义格式_biangabiang的博客-CSDN博客_fastjson自定义序列化格式 --使用阿里巴巴的fastjson,不过记得先配置Http消息转换器为FastJson(覆盖wms中的configureMessageConverters)
这是因为fastjson允许针对不同类型使用不同的序列化程序。
5.3媒体类型为JSON,且使用JackSon处理特定类型
无论是JackSon还是FastJson的,它们都是实现了HttpMessageConverter接口。 标准一样,细节有所区别而已。
所以,如果使用默认的JackSon的时候,可以和网上常常提到的FASTjson一样的思路来解决问题。
有关内容可以看这个:Jackson Tutorial | Baeldung
然而比较简单的方式还是覆盖下configureMessageConverters,在其中定制化MappingJackson2HttpMessageConverter的各种属性。
例如网上有这样的例子:
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER)
.serializationInclusion(JsonInclude.Include.NON_NULL);
return new MappingJackson2HttpMessageConverter(builder.build());
}
如果仅仅是想自定义序列化或者反序列化器,那么使用注解即可:
@JsonSerialize(using = FamilyJSONSerializer.class)
public class Family {
private Integer id;
private String name;
private Date addTime;
private Date lastOptime;
private String batchNo;
}
FamilyJSONSerializer的代码如下:
package study.config.message; import java.io.IOException; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider; import study.model.family.Family; public class FamilyJSONSerializer extends JsonSerializer<Family>{ @Override
public void serialize(Family value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value==null) {
gen.writeString("{}");
return;
}
gen.writeString(value.toString());
} @Override
public Class<Family> handledType(){
return Family.class;
}
}
自定义消息的解析,通常不是那么迫切,只要知道大概即可。
没有必要耗费太多的时间研究,并重新做一个轮子。
六、常用-响应消息(http消息转换)配置(响应)
spring的设计是允许有多个http消息转换器,每个转换器对应不同的媒体类型。这些转换器只要实现HttpMessageConverter接口即可。
当然如果你自己自定义,也可以让一个转换器对应n种媒体类型,或者n个转换器对应一个媒体类型。
如果是这种情况,spring会采用一定的选择缺略,保证每个媒体类型都可以进行适当的转换。
网上太多了,不再详细说明了。常见的即使用fastJson--覆盖wms中的configureMessageConverters。
下面是jackson的例子:
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
converters.add(new ResourceHttpMessageConverter());
converters.add(new ResourceRegionHttpMessageConverter());
MappingJackson2HttpMessageConverter jconverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper=jconverter.getObjectMapper();
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString("");
}
});
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(dateFormat);
converters.add(jconverter);
}
主要两点:设置日期格式、null输出为"",节约前端编码工作量。
七、常用-配置视图和资源解释
例如:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.addResourceLocations("classpath:/public/")
.addResourceLocations("classpath:/resources/")
.addResourceLocations("file:" + uploadPath);
} @Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("main/index");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}
八、小结
对于大部分的javaEE开发的工程师而言,都有必要理解webMvc的机制,以及wms的配置。
wms既简单又复杂,涉及到webMvc的方法面面,相关的源码非常之多,如要透彻了解其原理和机制只有一个方法:仔细阅读并做好笔记。
此外,建议在阅读本代码前,先掌握http请求的基本原理和流程。另外为了提高阅读和理解的效率,建议开启调试模式,逐步调试,就能够较快了解这里所涉及的有关知识。
我个人一直喜欢用这个方法。现在ide对于这个的支持非常好,无论是eclipse,idea还是netbean,似乎除了跟踪不到机器指令,任何东西都可以跟踪和窥探,强大到难以置信。
在调试过程中,可以发现代码是从web容器(或者服务器)开始执行的,并最好从org.springframework.web.servlet.DispatcherServlet开始,因为在此类之前的大部分属于容器的api。
Spring之WebMvcConfigurationSupport的更多相关文章
- HandlerMethodArgumentResolver 自定义使用
HandlerMethodArgumentResolver 自定义使用 1.HandlerMethodArgumentResolver 的应用场景 HandlerMethodArgumentRes ...
- Spring EnableWebMvc vs WebMvcConfigurationSupport
EnableWebMvc vs WebMvcConfigurationSupport spring doc解释 WebMvcConfigurationSupport: This is the main ...
- Spring boot 梳理 -@SpringBootApplication、@EnableAutoConfiguration与(@EnableWebMVC、WebMvcConfigurationSupport,WebMvcConfigurer和WebMvcConfigurationAdapter)
@EnableWebMvc=继承DelegatingWebMvcConfiguration=继承WebMvcConfigurationSupport 直接看源码,@EnableWebMvc实际上引入一 ...
- Spring 梳理 - JavaConfig、SPI、SCI、SpringSCI、WebApplicationInitializer、AbstractAnnotationConfigDispatcherServletInitializer、WebMvcConfigurationSupport
总结1: SCI:Servlet容器(Tomcat)提供的初始化Servlet容器本身的接口,可替换web.xml SpringSCI:SpringServletContainerInitialize ...
- Spring Boot中只能有一个WebMvcConfigurationSupport配置类
首先将结论写文章的最前面,一个项目中只能有一个继承WebMvcConfigurationSupport的@Configuration类(使用@EnableMvc效果相同),如果存在多个这样的类,只有一 ...
- spring boot 添加拦截器
构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Appli ...
- Spring MVC中使用 Swagger2 构建Restful API
1.Spring MVC配置文件中的配置 [java] view plain copy <!-- 设置使用注解的类所在的jar包,只加载controller类 --> <contex ...
- Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC
内容列表: 启用MVC Java config 或 MVC XML namespace 修改已提供的配置 类型转换和格式化 校验 拦截器 内容协商 View Controllers View Reso ...
- Spring MVC对象转换说明
在Spring MVC之前我们需要在Servlet里处理HttpServletRequest参数对象,但这个对象里的属性都是通用类型的对象(如字符串),处理起来很繁琐并且容易出错,而Spring MV ...
- Spring Boot 学习(2)
文 by / 林本托 Tips 做一个终身学习的人. 源代码:github下的/code01/ch2. 配置 Web 应用程序 在上一章中,我们学习了如何创建一个基本的应用程序模板,并添加了一些基本功 ...
随机推荐
- Postergresql常见操作
Postergresql常见操作 1. 安装部署 略 2. 登录数据库 查看版本 ## 以管理员身份 postgres 登陆,然后通过#psql -U postgres#sudo -i -u post ...
- springboot+kafka(centos7集群部署kafka)
1.kafka简介 1.1:Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动 ...
- 在网页上直接运行Win11,5秒内用AI克隆自己的声音 | 蛮三刀酱的Github周刊第二期
大家好,这里是每周更新的Github精彩分享周刊,我是每周都在搬砖的蛮三刀酱. 我会从Github热门趋势榜里选出 高质量.有趣,牛B 的开源项目进行分享. 1. PowerShell:不止于Wind ...
- 【停用词】NLP中的停用词怎么获取?我整理了6种方法
目录 一.停用词介绍 二.停用词应用场景 2.1 提取高频词 2.2 词云图 三.停用词获取方法 3.1 自定义停用词 3.2 用wordcloud调取停用词 3.3 用nltk调取停用词 3.3.1 ...
- git checkout 命令图文详解
目录 git checkout branchname (切换本地分支) 切换远程分支 放弃修改 git checkout . git checkout – filename git checkout ...
- XML Schema(XSD)详解:定义 XML 文档结构合法性的完整指南
XML Schema描述了 XML 文档的结构.XML Schema语言也称为 XML Schema Definition(XSD). <?xml version="1.0" ...
- postgresql 去重&查最新一组记录 关键词partition by
- threejs的坐标渲染和着色
点击查看代码 function createBasic() { // 目标:了解顶点坐标绘制正方形 // 1. 准备 BufferGemotry 缓冲几何图形 // 2. 准备 32 位浮点数的数组, ...
- C 语言编程 — 指令行参数
目录 文章目录 目录 前文列表 命令行参数 前文列表 <程序编译流程与 GCC 编译器> <C 语言编程 - 基本语法> <C 语言编程 - 基本数据类型> < ...
- angular 16 路由守卫更新
在 angular16 中守卫使用方式进行了更新,route 守卫被弃用(取消了CanActivate的使用),新增了功能性守卫(CanActivateFn),支持 inject 注入,官网提供了一个 ...