Spring MVC 十一:@EnableWebMvc

文章详细解析了@EnableWebMvc的使用、配置原理,以及它与SpringMVC自动配置的关系,包括web.xml简化、Controller扫描和处理中文乱码。@EnableWebMvc主要作用相当于<mvc:annotation-driven/>,通过与@Configuration结合注入SpringIoC容器。
摘要由CSDN通过智能技术生成

我们从两个角度研究@EnableWebMvc:

  1. @EnableWebMvc的使用
  2. @EnableWebMvc的底层原理
@EnableWebMvc的使用

@EnableWebMvc需要和java配置类结合起来才能生效,其实Spring有好多@Enablexxxx的注解,其生效方式都一样,通过和@Configuration结合、使得@Enablexxxx中的配置类(大多通过@Bean注解)注入到Spring IoC容器中。

理解这一配置原则,@EnableWebMvc的使用其实非常简单。

我们还是使用前面文章的案例进行配置。

新增配置类

在org.example.configuration包下新增一个配置类:

@Configuration
@EnableWebMvc
@ComponentScan({"org.example.controller"})
public class MvcConfiguration{
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for(HttpMessageConverter httpMessageConverter:converters){
            if(StringHttpMessageConverter.class.isAssignableFrom(httpMessageConverter.getClass())){
                ((StringHttpMessageConverter)httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
            }
        }
    }
}

配置类增加controller的包扫描路径,添加@EnableWebMvc注解,其他不需要干啥。

简化web.xml

由于使用了@EnableWebMvc,所以web.xml可以简化,只需要启动Spring IoC容器、添加DispatcherServlet配置即可

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
<!--  1、启动Spring的容器-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>
applicationContext.xml

Spring IoC容器的配置文件,指定包扫描路径即可:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan base-package="org.example">
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
</beans>
Springmvc.xml

springmvc.xml文件也可以简化,只包含一个视图解析器及静态资源解析的配置即可,其他的都交给@EnableWebMvc即可:

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

    <!-- 放行静态资源 -->
    <mvc:default-servlet-handler />

    <!-- 视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 视图前缀 -->
        <property name="prefix" value="/" />
        <!-- 视图后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

</beans>
测试

添加一个controller:

@Controller
public class    HelloWorldController {
    @GetMapping(value="/hello")
    @ResponseBody
    public String hello(ModelAndView model){
        return "<h1>@EnableWebMvc 你好</h1>";
    }
}

启动应用,测试:
在这里插入图片描述

发现有中文乱码。

解决中文乱码

参考上一篇文章,改造一下MvcConfiguration配置文件,实现WebMvcConfigurer接口、重写其extendMessageConverters方法:


@Configuration
@EnableWebMvc
@ComponentScan({"org.example.controller"})
public class MvcConfiguration implements WebMvcConfigurer{
    public MvcConfiguration(){
        System.out.println("mvc configuration constructor...");
    }
//    通过@EnableWebMVC配置的时候起作用,
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for(HttpMessageConverter httpMessageConverter:converters){
            if(StringHttpMessageConverter.class.isAssignableFrom(httpMessageConverter.getClass())){
                ((StringHttpMessageConverter)httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
            }
        }
    }

}

重启系统,测试:
在这里插入图片描述

中文乱码问题已解决。

问题:@EnableWebMvc的作用?

上述案例已经可以正常运行可,我们可以看到web.xml、applicationContext.xml以及springmvc.xml等配置文件都还在,一个都没少。

那么@EnableWebMvc究竟起什么作用?

我们去掉@EnableWebMvc配置文件试试看:项目中删掉MvcConfiguration文件。

重新启动项目,访问localhost:8080/hello,报404!

回忆一下MvcConfiguration文件中定义了controller的包扫描路径,现在MvcConfiguration文件被我们直接删掉了,controller的包扫描路径需要以其他方式定义,我们重新修改springmvc.xml文件,把controller包扫描路径加回来。

同时,我们需要把SpringMVC的注解驱动配置加回来:

    <!-- 扫描包 -->
    <context:component-scan base-package="org.example.controller"/>

    <mvc:annotation-driven />

以上两行加入到springmvc.xml配置文件中,重新启动应用:
在这里插入图片描述

应用可以正常访问了,中文乱码问题请参考上一篇文章,此处忽略。

因此我们是否可以猜测:@EnableWebMvc起到的作用等同于配置文件中的: <mvc:annotation-driven /> ?

@EnableWebMvc的底层原理

其实Spring的所有@Enablexxx注解的实现原理基本一致:和@Configuration注解结合、通过@Import注解引入其他配置类,从而实现向Spring IoC容器注入Bean。

@EnableWebMvc也不例外。

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

@EnableWebMvc引入了DelegatingWebMvcConfiguration类。看一眼DelegatingWebMvcConfiguration类,肯定也加了@Configuration注解的:

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
   ...

DelegatingWebMvcConfiguration类扩展自WebMvcConfigurationSupport,其实DelegatingWebMvcConfiguration并没有创建bean、实际创建bean的是他的父类WebMvcConfigurationSupport。

WebMvcConfigurationSupport按顺序注册如下HandlerMappings:

  1. RequestMappingHandlerMapping ordered at 0 for mapping requests to annotated controller methods.
  2. HandlerMapping ordered at 1 to map URL paths directly to view names.
  3. BeanNameUrlHandlerMapping ordered at 2 to map URL paths to controller bean names.
  4. HandlerMapping ordered at Integer.MAX_VALUE-1 to serve static resource requests.
  5. HandlerMapping ordered at Integer.MAX_VALUE to forward requests to the default servlet.

并注册了如下HandlerAdapters:

  1. RequestMappingHandlerAdapter for processing requests with annotated controller methods.
  2. HttpRequestHandlerAdapter for processing requests with HttpRequestHandlers.
  3. SimpleControllerHandlerAdapter for processing requests with interface-based Controllers.

注册了如下异常处理器HandlerExceptionResolverComposite:

  1. ExceptionHandlerExceptionResolver for handling exceptions through org.springframework.web.bind.annotation.ExceptionHandler methods.
  2. ResponseStatusExceptionResolver for exceptions annotated with org.springframework.web.bind.annotation.ResponseStatus.
  3. DefaultHandlerExceptionResolver for resolving known Spring exception types

以及:

Registers an AntPathMatcher and a UrlPathHelper to be used by:

  1. the RequestMappingHandlerMapping,
  2. the HandlerMapping for ViewControllers
  3. and the HandlerMapping for serving resources

Note that those beans can be configured with a PathMatchConfigurer.

Both the RequestMappingHandlerAdapter and the ExceptionHandlerExceptionResolver are configured with default instances of the following by default:

  1. a ContentNegotiationManager
  2. a DefaultFormattingConversionService
  3. an org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean if a JSR-303 implementation is available on the classpath
  4. a range of HttpMessageConverters depending on the third-party libraries available on the classpath.

因此,@EnableWebMvc确实与 <mvc:annotation-driven /> 起到了类似的作用:注册SpringWebMVC所需要的各种特殊类型的bean到Spring容器中,以便在DispatcherServlet初始化及处理请求的过程中生效!

上一篇 Spring MVC 十一:中文乱码

### 回答1: @enablewebmvc注解将会自动配置和引入大量的 Spring WebMvc 组件和特性。如果在使用了@enablewebmvc注解后@import不再生效,可能是因为该注解中已经配置好了需要的组件,因此无需再手动通过@import方式引入。 需要注意的是,@enablewebmvc注解会代替@Configuration和@EnableWebMvc注解,因此如果已经使用了这两个注解,就不需要再添加@enablewebmvc注解了。 ### 回答2: 使用@EnableWebMvc注解后,@Import注解失效的原因是@EnableWebMvc注解本身已经包含了@Import注解的功能。 @EnableWebMvc注解是Spring框架提供的一个类级别的注解,它的作用是开启Spring MVC的相关配置。该注解会自动为我们完成一些常用的配置,例如注册必要的组件和配置默认的处理器。在@EnableWebMvc注解内部,Spring框架已经使用了@Import注解来引入了一些必要的类,这些类包含了Spring MVC框架所需的所有配置。 因此,当我们使用了@EnableWebMvc注解时,已经包含了@Import注解的功能,所以我们不再需要显式地使用@Import注解来导入其他配置类。这也是为什么在使用@EnableWebMvc注解后,@Import注解不再起作用的原因。 总结起来,使用@EnableWebMvc注解后,无需使用@Import注解来导入其他配置类,因为@EnableWebMvc本身已经包含了所有必要的配置。 ### 回答3: 在Spring框架中,@EnableWebMvc注解用于启用Web MVC功能,它会自动为我们进行一些配置,例如处理HTTP请求和响应、渲染视图等。当我们使用@EnableWebMvc注解后,它会自动注册一些默认的配置类,如WebMvcConfigurerAdapter。 而在另一方面,@Import注解用于将指定的配置类导入到当前的配置类中。它可以用于注册额外的配置类,以提供其他的功能。 然而,由于@EnableWebMvc已经自动注册了WebMvcConfigurerAdapter类,它的注册会覆盖在@Import中导入的配置类,因此@Import注解失效了。 解决这个问题的方法是,我们可以直接在WebMvcConfigurerAdapter类中添加我们需要的配置,而不需要使用@Import注解导入其他的配置类。在WebMvcConfigurerAdapter类中,我们可以实现addInterceptors、addCorsMappings和addViewControllers等方法来自定义一个WebMvcConfigurer配置类,提供更多的自定义配置。 总之,在使用@EnableWebMvc注解时,需要注意它已经自动注册了WebMvcConfigurerAdapter类,以提供默认的配置。如果需要更多的自定义配置,可以直接在WebMvcConfigurerAdapter类中进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值