当前位置: 首页 > article >正文

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之后


http://www.kler.cn/a/461914.html

相关文章:

  • 电子应用设计方案85:智能 AI门前柜系统设计
  • 每天40分玩转Django:Django Celery
  • Redis(二)value 的五种常见数据类型简述
  • Elasticsearch: 高级搜索
  • df.groupby()方法使用表达式分组
  • docker使用国内镜像
  • 鸿蒙工程签名编译和上架
  • 【Linux】信号处理
  • Java重要面试名词整理(十八):Sentinel
  • 【马来西亚博特拉大主办】第五届电网系统与绿色能源国际学术会议(PGSGE 2025)
  • 【gopher的java学习笔记】依赖管理方式对比(go mod maven)
  • java中多线程的一些常见操作
  • Git快速入门(二)·本地仓库·GitHubDesktop的使用
  • 如何使用python清空特定路径下所有文件夹下中的文件,把空文件夹要保留下来
  • 【开源免费】基于Vue和SpringBoot的共享汽车管理系统(附论文)
  • 【ARM】Keil恢复默认设置
  • 低代码开发助力数字化转型的战略价值
  • vue的整理
  • C++中一些常用头文件及其解析
  • 大数据数仓Hive和数据集市、数据治理
  • [羊城杯 2024]hiden
  • IC验证面试常问问题
  • Lua : Coroutine(协程)
  • Linux(16)——安装和更新 RPM 软件包
  • 详细说明嵌入式linux中bootcmd与bootargs差异
  • leetcode hot 100 前k个高平元素