SpringMVC中那些Java Config

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: SpringMVC中那些Java Config

简单来讲,就是使用Java 配置替代以的xml配置。MVC Java配置和MVC XML namespace提供了适用于大多数应用程序的默认配置,并提供了一个用于自定义的配置API。

【1】启用MVC Configuration


在Java配置中,你可以使用@EnableWebMvc注解启用MVC configuration。如下所示:

@Configuration
@EnableWebMvc
public class WebConfig {
}

在XML配置中,你可以使用<mvc:annotation-driven>注解来启用MVC配置。如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven/>
</beans>

前面的示例注册了大量SpringMVC基础结构bean,并适应类路径上可用的依赖项(例如,JSON、XML和其他的有效负载转换器)。

【2】MVC配置API


在Java 配置中 你可以实现WebMvcConfigurer 接口,如下所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    // Implement configuration methods...
}


WebMvcConfigurer接口提供了一系列回调函数供你自定义配置。接口源码与说明如下:

public interface WebMvcConfigurer {
   //帮助配置HandlerMapping路径匹配选项,例如是否使用解析的PathPatterns或与PathPatterns匹配的字符串模式,
   //是否匹配尾部斜杠等。
  default void configurePathMatch(PathMatchConfigurer configurer) {
  }
   //配置内容协商/转换
  default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
  }
  /**
   * Configure asynchronous request handling options.
   */
   //配置异步请求处理
  default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
  }
   //配置一个处理器处理仍旧未被处理的请求,通常是转发哦到Servlet容器的"default"servlet
   //这方面的一个常见用例是DispatcherServlet映射到“/”从而覆盖Servlet容器对静态资源的默认处理。
  default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  }
   //注册额外的Converters和Formatters
  default void addFormatters(FormatterRegistry registry) {
  }
   //添加SpringMVC生命周期拦截器,用于控制器方法调用和资源处理程序请求的预处理和后处理。
   //可以注册拦截器以应用于所有请求,也可以将拦截器限制为URL 的子集。
  default void addInterceptors(InterceptorRegistry registry) {
  }
   添加处理程序以处理静态资源,例如web应用程序根目录下、classpath下和其他位置下的图像、js和css文件
  default void addResourceHandlers(ResourceHandlerRegistry registry) {
  }
   //配置跨域请求处理
  default void addCorsMappings(CorsRegistry registry) {
  }
   //配置预先配置了响应状态代码和/或视图的简单自动控制器,以呈现响应主体。
   //这在不需要自定义控制器逻辑的情况下非常有用,例如,呈现主页、执行简单的站点URL重定向、
   //返回包含HTML内容的404状态、返回不包含任何内容的204状态等等。
  default void addViewControllers(ViewControllerRegistry registry) {
  }
   //配置视图解析器,将从控制器返回的基于字符串的视图名称转换为具体的org.springframework.web.servlet.view实现,
   //以便使用执行渲染。
  default void configureViewResolvers(ViewResolverRegistry registry) {
  }
   //添加解析器以支持自定义控制器方法参数类型。
  //这不会覆盖解析处理程序方法参数的内置支持。
  //要自定义参数解析的内置支持,请直接配置RequestMappingHandlerAdapter
  default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
  }
   //添加处理器以支持自定义控制器方法返回值类型。
   //这不会覆盖springMVC对返回值处理的内置支持,如果想覆盖可以直接配置RequestMappingHandlerAdapter 
  default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
  }
   //配置HttpMessageConverters用于从request读取并写入response。如果没有添加converter,将会注册一系列默认的。
   //注意,通过该方法添加Converter,将会关闭默认converters的注册。如果只是想添加额外的Converter,
   //建议使用extendMessageConverters方法
  default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  }
   //注册默认converters后,运行你进行添加自定义转换器(也可以修改converters,通常不建议)
  default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  }
   //配置异常解析器。给定的resolvers开始可能为空,如果为空,框架会配置一系列默认的解析器,
   //参考WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers(List,ContentNegotiationManager)
   //或者,如果列表中添加了任何异常解析程序,则应用程序将有效地接管并必须提供完全初始化的异常解析程序。
   //你可以选择使用extendHandlerExceptionResolvers方法,该方法允许你对默认配置的异常解析器进行扩展或修改
  default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
  }
   //扩展或修改默认配置的异常解析器列表
  default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
  }
   //提供一个自定义的Validator替换掉框架默认创建的
   //在JSR-303中,默认实现是org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean
   //返回值为null表示使用默认配置。
  @Nullable
  default Validator getValidator() {
    return null;
  }
  /**
   * Provide a custom {@link MessageCodesResolver} for building message codes
   * from data binding and validation error codes. Leave the return value as
   * {@code null} to keep the default.
   */
   //提供自定义MessageCodesResolver,用于从数据绑定和验证错误代码生成消息代码。
   //返回值为null表示使用默认配置。
  @Nullable
  default MessageCodesResolver getMessageCodesResolver() {
    return null;
  }
}

【3】类型转换

默认情况下,会配置各种数字和日期类型的格式化器,并支持通过字段上的@NumberFormat@DateTimeFormat进行自定义。


如下实例,在Java config中注册自定义formatters 格式化器和converters类型转换器:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        // ...
    }
}


类似的,xml中配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven conversion-service="conversionService"/>
    <bean id="conversionService"
            class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="org.example.MyConverter"/>
            </set>
        </property>
        <property name="formatters">
            <set>
                <bean class="org.example.MyFormatter"/>
                <bean class="org.example.MyAnnotationFormatterFactory"/>
            </set>
        </property>
        <property name="formatterRegistrars">
            <set>
                <bean class="org.example.MyFormatterRegistrar"/>
            </set>
        </property>
    </bean>
</beans>

默认情况下,SpringMVC在解析和格式化日期值时考虑请求区域设置。这适用于将日期表示为“input”表单字段的字符串的表单。但是,对于"date" and "time" form fields,浏览器使用HTML规范中定义的固定格式。对于这种情况,日期和时间格式可以按如下方式自定义:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registrar.registerFormatters(registry);
    }
}

【4】Validation

默认情况下,如果类路径上存在Bean 校验器(例如Hibernate Validator),则LocalValidatorFactoryBean将注册为全局验证程序,以便@Valid@Validated 与控制器方法参数一起使用。v


在Java 配置中,你可以定义一个全局的Validator 实例,如下所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public Validator getValidator() {
        // ...
    }
}


等同的xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven validator="globalValidator"/>
</beans>

你也可以选择局部注册Validator ,如下所示:

@Controller
public class MyController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new FooValidator());
    }
}

如果需要在某处注入LocalValidatoryFactoryBean,请创建一个bean并用@Primary标记它,以避免与MVC配置中声明的bean冲突。

【5】拦截器


在Java配置中,您可以注册拦截器以应用于传入的请求,如下例所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LocaleChangeInterceptor());
        registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
        registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
    }
}

等同的xml配置如下:

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/admin/**"/>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/secure/*"/>
        <bean class="org.example.SecurityInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

【6】Content Types


您可以配置SpringMVC如何根据请求确定请求的内容类型(例如,Accept头、URL路径扩展、查询参数等)。

默认情况下,值检测Accept 头。如果必须使用基于URL的内容类型解析,请考虑在路径扩展上使用查询参数策略。


在Java配置中,您可以自定义请求的内容类型解析,如下例所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.mediaType("json", MediaType.APPLICATION_JSON);
        configurer.mediaType("xml", MediaType.APPLICATION_XML);
    }
}


等同的xml配置如下所示:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="mediaTypes">
        <value>
            json=application/json
            xml=application/xml
        </value>
    </property>
</bean>

【7】Message Converters

在Java config中你可以自定义HttpMessageConverter 通过覆盖configureMessageConverters()方法(替换SpringMVC提供的默认converters )或者覆盖extendMessageConverters()方法(自定义默认的converters或者额外添加converters)。


以下示例使用自定义的ObjectMapper(而不是默认的ObjectMapper)添加XML和Jackson JSON转换器:

@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
                .indentOutput(true)
                .dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
                .modulesToInstall(new ParameterNamesModule());
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    }
}

在前面的示例中,Jackson2ObjectMapperBuilder 用于为MappingJackson2HttpMessageConverter 和MappingJackson2XmlHttpMessageConverter 创建通用配置,启用indentation 、自定义日期格式和 jackson-module-parameter-names模块的注册,它增加了对访问参数名的支持(Java8中添加的一个特性)。


此生成器自定义Jackson的默认属性,如下所示:


DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 被禁用


MapperFeature.DEFAULT_VIEW_INCLUSION 被禁用


如果在类路径上检测到以下知名模块,它还会自动注册这些模块:


jackson-datatype-joda: Support for Joda-Time types.


jackson-datatype-jsr310: Support for Java 8 Date and Time API types.


jackson-datatype-jdk8: Support for other Java 8 types, such as Optional.


jackson-module-kotlin: Support for Kotlin classes and data classes.


启用Jackson XML支持的缩进需要woodstox-core-asl依赖项和jackson-dataformat-xml 依赖项。


还有其他有趣的Jackson模块:


jackson-datatype-money: Support for javax.money types (unofficial module).


jackson-datatype-hibernate: Support for Hibernate-specific types and properties (including lazy-loading aspects).

等同的xml配置如下所示:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="objectMapper"/>
        </bean>
        <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
            <property name="objectMapper" ref="xmlMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
      p:indentOutput="true"
      p:simpleDateFormat="yyyy-MM-dd"
      p:modulesToInstall="com.fasterxml.jackson.module.paramnames.ParameterNamesModule"/>
<bean id="xmlMapper" parent="objectMapper" p:createXmlMapper="true"/>

【8】 View Controllers


这是定义ParameterableViewController的快捷方式,该控制器在调用时立即转发到视图。可以在静态情况下使用它,也就是当视图生成响应之前没有Java控制器逻辑运行。


以下Java配置示例将请求/转发到名为home的视图:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}

等同的xml配置如下所示:

<mvc:view-controller path="/" view-name="home"/>


当一个标注了@RequestMapping方法匹配到URL,则view controller不能再处理该URL。


如果@RequestMapping方法映射到任何HTTP方法的某个URL,则视图控制器不能用于处理同一URL。这是因为URL与带注解控制器的匹配被认为是端点所有权的足够强的声明,因此可以将405(METHOD_NOT_ALLOWED)、415(UNSUPPORTED_MEDIA_TYPE)或类似响应发送到客户端以帮助调试。因此,建议避免在带注解的控制器和视图控制器view controller之间拆分URL处理。


【9】 视图解析器

MVC configuration 简化了视图解析器的注册。以下Java配置示例通过使用JSPJackson作为JSON呈现的默认视图来配置内容协商视图解析:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new MappingJackson2JsonView());
        registry.jsp();
    }
}

等同的xml配置如下:

<mvc:view-resolvers>
    <mvc:content-negotiation>
        <mvc:default-views>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
        </mvc:default-views>
    </mvc:content-negotiation>
    <mvc:jsp/>
</mvc:view-resolvers>

但是,请注意,FreeMarker、Tiles、Groovy Markup和script templates也需要配置底层视图技术。

MVC命名空间提供专用元素。以下示例适用于FreeMarker:

<mvc:view-resolvers>
    <mvc:content-negotiation>
        <mvc:default-views>
            <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
        </mvc:default-views>
    </mvc:content-negotiation>
    <mvc:freemarker cache="false"/>
</mvc:view-resolvers>
<mvc:freemarker-configurer>
    <mvc:template-loader-path location="/freemarker"/>
</mvc:freemarker-configurer>

在Java配置中,您可以添加相应的Configurer bean,如下例所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new MappingJackson2JsonView());
        registry.freeMarker().cache(false);
    }
    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPath("/freemarker");
        return configurer;
    }
}

【10】Static Resources

此选项提供了一种方便的方法,可以从Resource-based 的位置列表中快速访问静态资源。


在下一个示例中,给定一个以/resources开头的请求,然后在web应用程序根目录下/public或在classpath:/static/目录下的类路径上查找和提供静态资源。


这些资源的使用期限为一年,以确保最大限度地利用浏览器缓存,并减少浏览器发出的HTTP请求。最后Last-Modified 的信息是从Resource#lastModified推导出来的,因此HTTP请求需要支持“Last-Modified”头。


Java 配置实例如下:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
            .addResourceLocations("/public", "classpath:/static/")
            .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)));
    }
}


等同的xml配置如下:

<mvc:resources mapping="/resources/**"
    location="/public, classpath:/static/"
    cache-period="31556926" />


资源处理程序还支持ResourceResolver 实现链和ResourceTransformer 实现链,您可以使用它们创建用于处理优化资源的工具链。


您可以基于从内容、固定应用程序版本或其他内容计算的MD5哈希将VersionResourceResolver用于已版本化的资源URL。ContentVersionStrategy (MD5哈希)是一个不错的选择 — 除了一些值得注意的例外,比如模块加载器使用的JavaScript资源。


下面实例展示了在Java配置如何使用VersionResourceResolver :

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public/")
                .resourceChain(true)
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
    }
}


等同的xml配置如下所示:

<mvc:resources mapping="/resources/**" location="/public/">
    <mvc:resource-chain resource-cache="true">
        <mvc:resolvers>
            <mvc:version-resolver>
                <mvc:content-version-strategy patterns="/**"/>
            </mvc:version-resolver>
        </mvc:resolvers>
    </mvc:resource-chain>
</mvc:resources>


然后,您可以使用ResourceUrlProvider 重写URL并应用整个解析程序和转换器链 — 例如,插入版本。MVC配置提供了一个ResourceUrlProvider bean,以便可以将其注入到其他配置中。您还可以使用ResourceUrlEncodingFilter 对Thymeleaf、JSP、FreeMarker和其他依赖HttpServletResponse#encodeURL的URL标记的文件进行透明重写。


请注意,当同时使用EncodedResourceResolver (例如,用于服务Gzip或brotli编码的资源)和VersionResourceResolver时,必须按此顺序注册它们。这确保了基于内容的版本始终基于未编码的文件可靠地计算。


WebJars 还通过WebJarsResourceResolver 得到支持,当org.webjars:webjars-locator-core核心库出现在类路径上时,WebJarsResourceResolver资源解析器会自动注册。解析器可以重写URL以包含jar的版本,还可以匹配没有版本的传入URL — 例如,从/jquery/jquery.min.js到/jquery/1.2.0/jquery.min.js。


【11】Default Servlet


SpringMVC允许将DispatcherServlet映射到/(从而覆盖容器的默认Servlet的映射),同时仍然允许容器的默认Servlet处理静态资源请求。它使用/**的URL映射配置DefaultServletHttpRequestHandler,并且相对于其他URL映射具有最低优先级。


DefaultServletHttpRequestHandler转发所有请求到default Servlet.因此,它必须在所有其他URL HandlerMappings的顺序中保持最后一个。如果使用<mvc:annotation-driven>,就是这种情况。或者,如果设置自己的自定义HandlerMapping实例,请确保将其order属性设置为低于DefaultServletHttpRequestHandler的值,即Integer.MAX_VALUE。DefaultServletHttpRequestHandler中处理请求方法如下所示:

@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
Assert.state(this.servletContext != null, "No ServletContext set");
RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
if (rd == null) {
  throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
      this.defaultServletName + "'");
}
rd.forward(request, response);
}

以下示例显示如何使用默认设置启用该功能:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

等同的xml配置如下所示:

<mvc:default-servlet-handler/>

重写/Servlet映射的注意事项是,必须按名称而不是路径检索默认Servlet的RequestDispatcher。DefaultServletHttpRequestHandler 尝试在启动时自动检测容器的默认Servlet,使用大多数主要Servlet容器(包括Tomcat、Jetty、GlassFish、JBoss、Resin、WebLogic和WebSphere)的已知名称列表。如果默认Servlet已使用不同的名称进行自定义配置,或者如果在默认Servlet名称未知的情况下使用不同的Servlet容器,则必须显式提供默认Servlet的名称,如以下示例所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable("myCustomDefaultServlet");
    }
}

下示例显示了如何在XML中实现相同的配置:

<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>

【12】Path Matching

您可以自定义与路径匹配和URL处理相关的选项。更多详情参考PathMatchConfigurer.


以下示例显示如何在Java配置中自定义路径匹配:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer
            .setPatternParser(new PathPatternParser())
            .addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
    }
    private PathPatternParser patternParser() {
        // ...
    }
}

以下示例显示了如何在XML中实现相同的配置:

<mvc:annotation-driven>
    <mvc:path-matching
        trailing-slash="false"
        path-helper="pathHelper"
        path-matcher="pathMatcher"/>
</mvc:annotation-driven>
<bean id="pathHelper" class="org.example.app.MyPathHelper"/>
<bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>


【13】Advanced Java Config

@EnableWebMvc导入了DelegatingWebMvcConfiguration 其作用如下:

  • 为SpringMVC应用程序提供默认Spring配置
  • 检测并委托WebMVCConfiguer实现以自定义该配置。


对于高级模式,您可以删除@EnableWebMvc并直接从DelegatingWebMvcConfiguration配置扩展,而不是实现WebMVC配置,如下例所示:

@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {
    // ...
}


您可以在WebConfig中保留现有方法,但现在还可以覆盖基类中的bean声明,并且在类路径上仍然可以有任意数量的其他WebMVCConfiguer实现。


【14】Advanced XML Config


MVC命名空间没有高级模式。如果需要在bean上自定义一个不能更改的属性,可以使用Spring ApplicationContextBeanPostProcessor 生命周期挂钩,如下例所示:

@Component
public class MyPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        // ...
    }
}

注意,您需要将MyPostProcessor声明为bean,可以用XML显式地声明,也可以通过<component scan/>声明使其被检测。

【15】创建初始化类,代替web.xml

在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。 Spring提供了这个接口的实现,名为org.springframework.web.SpringServletContainerInitializer。


9dbcf840be7f43aa86f8cc72ba5a2305.png


SpringServletContainerInitializer这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。

Spring3.2引入了一个便利的WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。


WebApplicationInitializer实现类图示

//web工程的初始化类,用来代替web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * 指定spring的配置类
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    /**
     * 指定springMVC的配置类
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }
    /**
     * 指定DispatcherServlet的映射规则,即url-pattern
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    /**
     * 注册过滤器
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
    }
}

创建SpringConfig配置类,代替spring的配置文件

ssm整合之后,spring的配置信息写在此类中

@Configuration
public class SpringConfig {
//...
}

【16】创建WebConfig配置类,代替SpringMVC的配置文件

/**
 * 代替SpringMVC的配置文件:
 * 1、扫描组件   2、视图解析器     3、view-controller    4、default-servlet-handler
 * 5、mvc注解驱动    6、文件上传解析器   7、异常处理      8、拦截器
 */
//将当前类标识为一个配置类
@Configuration
//1、扫描组件
@ComponentScan("com.mvc.controller")
//5、mvc注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    //4、default-servlet-handler
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
    //8、拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        TestInterceptor testInterceptor = new TestInterceptor();
        registry.addInterceptor(testInterceptor).addPathPatterns("/**");
    }
    //3、view-controller
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }
    //6、文件上传解析器
    @Bean
    public MultipartResolver multipartResolver(){
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        return commonsMultipartResolver;
    }
    //7、异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();
        prop.setProperty("java.lang.ArithmeticException", "error");
        exceptionResolver.setExceptionMappings(prop);
        exceptionResolver.setExceptionAttribute("exception");
        resolvers.add(exceptionResolver);
    }
    //配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }
    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
}
目录
相关文章
|
7天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
22 2
|
19天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
27天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
43 1
Spring 框架:Java 开发者的春天
|
27天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
27天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
65 2
|
1月前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
36 1
|
1月前
|
Java BI 调度
Java Spring的定时任务的配置和使用
遵循上述步骤,你就可以在Spring应用中轻松地配置和使用定时任务,满足各种定时处理需求。
125 1
|
13天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
28 0
|
1月前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?
|
1月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
36 9