SpringBoot整合SpringMVC, SpringBoot扩展SpringMVC
SpringBoot整合SpringMVC
把SpringMVC里面的一些内容整合到SpringBoot当中
中央转发器(DispatcherServlet)
中央转发器DispatcherServlet被springboot自动接管,不再需要我们在web.xml中配置,我们现在的项目也不是web项目,也不存在web.xml
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
DispatcherServletAutoConfiguration类主要包含了两个内部类,分别是
1、DispatcherServletConfiguration
2、DispatcherServletRegistrationConfiguration
顾名思义,前者是配置DispatcherServlet,后者是配置DispatcherServlet的注册类。什么是注册类?我们知道Servlet实例是要被添加(注册)到如tomcat这样的ServletContext里的,这样才能够提供请求服务。所以,DispatcherServletRegistrationConfiguration将生成一个Bean,负责将DispatcherServlet给注册到ServletContext中。
package org.springframework.boot.autoconfigure.web.servlet;
@AutoConfigureOrder(Integer.MIN_VALUE)
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({DispatcherServlet.class})
@AutoConfigureAfter({ServletWebServerFactoryAutoConfiguration.class})
public class DispatcherServletAutoConfiguration {
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";
public DispatcherServletAutoConfiguration() {
}
@Order(2147483637)
private static class DispatcherServletRegistrationCondition extends SpringBootCondition {
private DispatcherServletRegistrationCondition() {
}
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
ConditionOutcome outcome = this.checkDefaultDispatcherName(beanFactory);
return !outcome.isMatch() ? outcome : this.checkServletRegistration(beanFactory);
}
private ConditionOutcome checkDefaultDispatcherName(ConfigurableListableBeanFactory beanFactory) {
boolean containsDispatcherBean = beanFactory.containsBean("dispatcherServlet");
if (!containsDispatcherBean) {
return ConditionOutcome.match();
} else {
List<String> servlets = Arrays.asList(beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false));
return !servlets.contains("dispatcherServlet") ? ConditionOutcome.noMatch(this.startMessage().found("non dispatcher servlet").items(new Object[]{"dispatcherServlet"})) : ConditionOutcome.match();
}
}
private ConditionOutcome checkServletRegistration(ConfigurableListableBeanFactory beanFactory) {
ConditionMessage.Builder message = this.startMessage();
List<String> registrations = Arrays.asList(beanFactory.getBeanNamesForType(ServletRegistrationBean.class, false, false));
boolean containsDispatcherRegistrationBean = beanFactory.containsBean("dispatcherServletRegistration");
if (registrations.isEmpty()) {
return containsDispatcherRegistrationBean ? ConditionOutcome.noMatch(message.found("non servlet registration bean").items(new Object[]{"dispatcherServletRegistration"})) : ConditionOutcome.match(message.didNotFind("servlet registration bean").atAll());
} else if (registrations.contains("dispatcherServletRegistration")) {
return ConditionOutcome.noMatch(message.found("servlet registration bean").items(new Object[]{"dispatcherServletRegistration"}));
} else {
return containsDispatcherRegistrationBean ? ConditionOutcome.noMatch(message.found("non servlet registration bean").items(new Object[]{"dispatcherServletRegistration"})) : ConditionOutcome.match(message.found("servlet registration beans").items(Style.QUOTE, registrations).append("and none is named dispatcherServletRegistration"));
}
}
private ConditionMessage.Builder startMessage() {
return ConditionMessage.forCondition("DispatcherServlet Registration", new Object[0]);
}
}
@Order(2147483637)
private static class DefaultDispatcherServletCondition extends SpringBootCondition {
private DefaultDispatcherServletCondition() {
}
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition("Default DispatcherServlet", new Object[0]);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
List<String> dispatchServletBeans = Arrays.asList(beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false));
if (dispatchServletBeans.contains("dispatcherServlet")) {
return ConditionOutcome.noMatch(message.found("dispatcher servlet bean").items(new Object[]{"dispatcherServlet"}));
} else if (beanFactory.containsBean("dispatcherServlet")) {
return ConditionOutcome.noMatch(message.found("non dispatcher servlet bean").items(new Object[]{"dispatcherServlet"}));
} else {
return dispatchServletBeans.isEmpty() ? ConditionOutcome.match(message.didNotFind("dispatcher servlet beans").atAll()) : ConditionOutcome.match(message.found("dispatcher servlet bean", "dispatcher servlet beans").items(Style.QUOTE, dispatchServletBeans).append("and none is named dispatcherServlet"));
}
}
}
@Configuration(
proxyBeanMethods = false
)
@Conditional({DispatcherServletRegistrationCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({WebMvcProperties.class})
@Import({DispatcherServletConfiguration.class})
protected static class DispatcherServletRegistrationConfiguration {
protected DispatcherServletRegistrationConfiguration() {
}
@Bean(
name = {"dispatcherServletRegistration"}
)
@ConditionalOnBean(
value = {DispatcherServlet.class},
name = {"dispatcherServlet"}
)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath());
registration.setName("dispatcherServlet");
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}
}
@Configuration(
proxyBeanMethods = false
)
@Conditional({DefaultDispatcherServletCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({WebMvcProperties.class})
protected static class DispatcherServletConfiguration {
protected DispatcherServletConfiguration() {
}
@Bean(
name = {"dispatcherServlet"}
)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean({MultipartResolver.class})
@ConditionalOnMissingBean(
name = {"multipartResolver"}
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
}
}
springboot mvc自动配置(一)自动配置DispatcherServlet和DispatcherServletRegistry - __lay - 博客园
控制器(controller)
Controller作为一个springBoot的bean组件,是要被包扫描时自动导入IOC容器中的,然后实现自动管理
视图解析器(viewResolver)
包含ContentNegotiatingViewResolver还有BeanNameViewResolver两种视图解析器
multipartResolver也是自动配置好的
静态资源访问(默认classpath/static/**)
配置静态资源的地址:
这表示只有静态资源的访问路径为/resources/**时,才会处理请求
spring.mvc.static-path-pattern=/resources/**,
用于告诉Spring Boot应该在何处查找静态资源文件,这是一个列表性的配置,查找文件时会依赖于配置的先后顺序依次进行
spring.web.resources.static-locations=classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources
等同于SpringMVC.xml的以下配置:
<mvc:resources mapping="/resources/**" location="/public-resources/">
<mvc:cache-control max-age="3600" cache-public="true"/>
</mvc:resources>
默认的静态资源location
classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public
消息转换器(**HttpMessageConverter)
自动配置消息转换器
springWebMVC包 => org.springframework.web.servlet.config.annotation包下面的WebMvcConfigurationSupport类,在这个下面有个addDefaultHttpMessageConverters方法就是设置默认的消息转换器集合
默认是4种(ByteArrayHttpMessageConverter,StringHttpMessageConverter,ResourceHttpMessageConverter,ResourceRegionHttpMessageConverter),
然后会根据pom依赖(检测类是否存在),去添加其他类型的消息转换器
会根据需要添加:
MappingJackson2HttpMessageConverter、Jaxb2RootElementHttpMessageConverter之类的消息转换器
SpringBoot配置消息转换器_springboot 消息转换器-CSDN博客
格式化(FormaterRegistry)
静态资源管理()
SpringBoot扩展SpringMVC
自定义WebConfigurer
1.注册视图控制器(请求转发)
2.注册格式化器(比如日期)
3.注册消息转换器扩展(fastjson或者jackson或者Gson)
4.注册拦截器
@Configuration
public class MyWebMVC implements WebMvcConfigurer {
// 注册视图控制器(请求转发)
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/zxk").setViewName("index");
}
// 注册格式化器(比如日期)
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<Date>() {
@Override
public String print(Date date, Locale locale) {
return null;
}
@Override
public Date parse(String s, Locale locale) throws ParseException {
return new SimpleDateFormat("yyyy-MM-dd").parse(s);
}
});
}
// 注册消息转换器扩展(fastjson或者jackson或者Gson)
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fc = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fc.setFastJsonConfig(fastJsonConfig);
converters.add(fc);
}
// 注册拦截器,拦截器本身不需要被spring容器管理,在这里我们把自定义拦截器加入拦截器链
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyIntercepter())
.addPathPatterns("/**")// 所有请求都拦截
.excludePathPatterns("/zxk");// 放开/zxk
}
// 其他配置
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
WebMvcConfigurer.super.configurePathMatch(configurer);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
WebMvcConfigurer.super.configureContentNegotiation(configurer);
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
WebMvcConfigurer.super.configureAsyncSupport(configurer);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
WebMvcConfigurer.super.configureDefaultServletHandling(configurer);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
WebMvcConfigurer.super.addResourceHandlers(registry);
}
// 跨域策略配置
@Override
public void addCorsMappings(CorsRegistry registry) {
WebMvcConfigurer.super.addCorsMappings(registry);
}
// 视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
WebMvcConfigurer.super.configureViewResolvers(registry);
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
WebMvcConfigurer.super.addReturnValueHandlers(handlers);
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
WebMvcConfigurer.super.extendMessageConverters(converters);
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
WebMvcConfigurer.super.configureHandlerExceptionResolvers(resolvers);
}
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
WebMvcConfigurer.super.extendHandlerExceptionResolvers(resolvers);
}
// 请求字段校验
@Override
public Validator getValidator() {
return WebMvcConfigurer.super.getValidator();
}
@Override
public MessageCodesResolver getMessageCodesResolver() {
return WebMvcConfigurer.super.getMessageCodesResolver();
}
}
实体类User
public class User {
private String username;
private String password;
private int age;
private int score;
private int gender;
@JSONField(format = "yyyy-MM-dd")
private Date date;
}
自定义拦截器
public class MyIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("前置拦截");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("后置拦截");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("最终拦截");
}
}
自定义Servlet三大组件
自定义监听器
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("自定义监听器初始化!");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("自定义监听器销毁!");
}
}
自定义Servlet
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("自定义servlet映射get请求!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("自定义servlet映射post请求!");
}
@Override
public void destroy() {
System.out.println("自定义servlet销毁!");
}
@Override
public void init() throws ServletException {
System.out.println("自定义servlet初始化!");
}
}
自定义过滤器
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("自定义过滤器初始化");
}
@Override
public void destroy() {
System.out.println("自定义过滤器销毁");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
System.out.println("自定义过滤器执行过滤!");
}
}
最后在自定义的WebConfigurer类中注册分别bean
@Configuration
public class MyWebMVC implements WebMvcConfigurer {
// 其他代码......
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new
ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello", "/myServlet"));
return registrationBean;
}
@Bean
public ServletRegistrationBean myServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new
MyServlet(), "/myServlet");
return registrationBean;
}
}
当我们启动SpringBoot之后