SpringMVC中那些Java Config

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 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;
    }
}
目录
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
58 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
239 12
基于开源框架Spring AI Alibaba快速构建Java应用
|
3月前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
98 1
Spring 框架:Java 开发者的春天
|
3月前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
3月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
136 2
|
2月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
54 0
|
4月前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
3172 13
|
3月前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
61 1
|
3月前
|
Java BI 调度
Java Spring的定时任务的配置和使用
遵循上述步骤,你就可以在Spring应用中轻松地配置和使用定时任务,满足各种定时处理需求。
169 1