《SpringBoot》第04章 个性化定制

SpringBoot定制化开发

1.定制化方式

  1. 开启默认组件。可以通过修改配置文件application.properties的方式
  2. 替换默认组件。可以编写自定义的配置类 xxxAutoConfiguration + @Bean,以此来增加、替换容器中默认组件,可以达到替换组件的目的,底层更多是借助@ConditionalOnMissingBean注解,优先使用自定义的,否则使用默认的
  3. 重写 WebMvcConfigurer 接口 + @Component,可定制化Web功能**(推荐使用)**
  4. 重写 WebMvcConfigurer 接口 + @EnableWebMvc 可以全面接管Web,但这样会导致默认的规则全部失效,需要全部重新配置

2.WebMvcConfigurer 接口

下面介绍该接口,并对常用方法解析

public interface WebMvcConfigurer {

    // 配置路由匹配规则
	default void configurePathMatch(PathMatchConfigurer configurer) {}

	default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}

	default void configureAsyncSupport(AsyncSupportConfigurer configurer) {}

    // 默认静态资源处理器
	default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}

	default void addFormatters(FormatterRegistry registry) {}

    // 自定义拦截器配置
	default void addInterceptors(InterceptorRegistry registry) {}

    // 添加静态资源访问
	default void addResourceHandlers(ResourceHandlerRegistry registry) {}

	default void addCorsMappings(CorsRegistry registry) {}

    // 添加视图解析器(添加一个页面跳转)
	default void addViewControllers(ViewControllerRegistry registry) {}

	default void configureViewResolvers(ViewResolverRegistry registry) {}

	default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {}

	default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {}

	default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {}

	default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {}

	default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}

	default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {}

	@Nullable
	default Validator getValidator() {
		return null;
	}

	@Nullable
	default MessageCodesResolver getMessageCodesResolver() {
		return null;
	}
}

<1> addInterceptors()

@Bean
public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer(){

        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new FirstInterceptor())
                    .addPathPatterns("/**")  // 设置拦截路径
                    .excludePathPatterns("/index5"); // 设置拦截排除路径
        }
    };
}

<2> addResourceHandlers()

添加处理程序以从 Web 应用程序根目录、类路径等的特定位置提供静态资源,例如图像、js 和 css 文件。

@Bean
public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer(){

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            // addResoureHandler:指的是对外暴露的访问路径
		   // addResourceLocations:指的是内部文件放置的目录
            registry.addResourceHandler("/**").addResourceLocations("classpath:/h3c/");
        }

    };
}

<3> addViewControllers()

配置视图跳转控制

@Bean
public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer(){

        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/toLogin").setViewName("index2");
        }

    };
}

<4> configureViewResolvers()

配置视图解析器以将从控制器返回的基于字符串的视图名称转换为具体的 {@link org.springframework.web.servlet.View} 实现以执行渲染

/**
 * Configure view resolvers to translate String-based view names returned from
 * controllers into concrete {@link org.springframework.web.servlet.View}
 * implementations to perform rendering with.
 * @since 4.1
 */
default void configureViewResolvers(ViewResolverRegistry registry) {
}

配置实例

@Bean
public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer(){

        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix("/WEB-INF/jsp/");
            resolver.setSuffix(".jsp");
            registry.viewResolver(resolver);
        }
    };
}

3.@EnableWebMvc 会导致默认规则失效

当我们添加配置类,只实现了WebMvcConfigurer接口,这样可以向容器中添加自定义配置,但是如果使用了@EnableWebMvc会导致默认配置全部失效,为何呢?

@EnableWebMvc添加以后会向容器中注入一个DelegatingWebMvcConfiguration.class

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class) // 引入类
public @interface EnableWebMvc {}

注入的类中有两点需要关注:

  1. 该类继承了WebMvcConfigurationSupport
  2. 该类中的setConfigurers()会将所有的WebMvcConfigurer全部存入,这代表的意思是存在多个自定义配置类,系统会把配置合并到一起
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { // 注意继承了该类,下面会用到

   private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();


   @Autowired(required = false)
   public void setConfigurers(List<WebMvcConfigurer> configurers) {
      if (!CollectionUtils.isEmpty(configurers)) {
         // 这里参数是个集合,代表当存在多个自定义配置,会把配置合并到一起
         this.configurers.addWebMvcConfigurers(configurers);
      }
   }
   
   // 省略部分代码...
}

而我们的自动配置类WebMvcAutoConfiguration,在其条件中有很重要的一条@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),而@EnableWebMvc导入的类正好继承了WebMvcConfigurationSupport,所以如果我们通过@EnableWebMvc + WebMvcConfigurer来自定义配置的话,自动配置的东西就会全部失效,需要我们全部重写

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // 注意看这里,当WebMvcConfigurationSupport不存在
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {}

结论:如果我们定义接口实现WebMvcConfigurer,那么系统会把自定义的配置和默认配置合并一起,如果使用了@EnableWebMvc,那么配置全部失效,需要重写,那么相比之下,显而易见应该用哪个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为人师表好少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值