Spring注解@EnableWebMvc使用的坑点及解析

目录
  • Spring注解@EnableWebMvc使用坑点
  • @enablewebmvc注解有什么用途

Spring注解@EnableWebMvc使用坑点

通过注解的方式来进行Spring4 MVC开发时,我们都会在配置文件中加入<mvc:annotation-driven/>标签,这个配置会自动注册了一个 RequestMappingHandlerMapping、一个RequestMappingHandlerAdapter、以及一个ExceptionHandlerExceptionResolver 以支持使用注解Controller的注解方法(如@RequestMapping、@ExceptionHandler)来处理request,并开启一系列默认功能设置。

<!-- 开启SpringMVC注解模式 -->
<!-- 提供一系列功能:数据绑定,数字和日期format @NumberFormat,
@DataTimeFormat,xml/json默认读写支持-->
<mvc:annotation-driven/>

如果没有配置<mvc:annotation-driven/>,org.springframework.web.servlet.DispatcherServlet无法找到控制器并把请求分发到控制器。

添加上<mvc:annotation-driven/>后,请求会被相应的Controller处理。然而这时访问静态资源可能就不好使了,怎么办?一般可以使用 <mvc:default-servlet-handler />这个标签

<!-- 静态资源默认servlet配置
   1.加入对静态资源的处理:js/gif
   2.允许使用"/"做整体映射
-->
<mvc:default-servlet-handler />

所以这两个标签一般放在一起使用。

在Spring Boot中使用@EnableWebMvc也可能遇到类似的问题,@EnableWebMvc是使用注解方式快捷配置Spring Webmvc的一个注解。

在使用时你可能会遇到以下问题:

  • Spring Boot在application文件中的配置失效
  • 在Spring Boot的自定义配置类加上@EnableWebMvc后,发现自动配置的静态资源路径(classpath:/META/resources/,classpath:/resources/,classpath:/static/,classpath:/public/)资源无法访问。

通过查看@EnableWebMvc的源码,可以发现该注解就是为了引入一个DelegatingWebMvcConfiguration 配置类,而DelegatingWebMvcConfiguration又继承于WebMvcConfigurationSupport。也就是说,如果我们使用@EnableWebMvc就相当于导入了WebMvcConfigurationSupport类,这个时候,Spring Boot的自动装配就不会发生了,我们能用的,只有WebMvcConfigurationSupport提供的若干个配置。其实不使用@EnableWebMvc注解也是可以实现配置Webmvc,只需要将配置类继承于WebMvcConfigurationSupport类即可。

  • 当使用@EnableWebMvc时,加载的是WebMvcConfigurationSupport中的配置项。
  • 当不使用@EnableWebMvc时,使用的是WebMvcAutoConfiguration引入的配置项。

查看一下WebMvcAutoConfiguration 的源码:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
  ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
 ...
}

可以看到自动配置类 WebMvcAutoConfiguration 上有条件注解

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

这个注解的意思是在项目类路径中缺少 WebMvcConfigurationSupport类型的bean时改自动配置类才会生效。

有时候我们需要自己定制一些项目的设置,可以有以下几种使用方式:

  • @EnableWebMvc+extends WebMvcConfigurationAdapter,在扩展的类中重写父类的方法即可,这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置
  • extends WebMvcConfigurationSupport,在扩展的类中重写父类的方法即可,这种方式会屏蔽springboot的@EnableAutoConfiguration中的设置
  • extends WebMvcConfigurationAdapter/WebMvcConfigurer,在扩展的类中重写父类的方法即可,这种方式依旧使用springboot的@EnableAutoConfiguration中的设置

WebMvcConfigurer 没有暴露高级设置,如果需要高级设置 需要第二种方式继承WebMvcConfigurationSupport或者DelegatingWebMvcConfiguration,例如:

   @Configuration
   @ComponentScan(basePackageClasses = { MyConfiguration.class })
   public class MyConfiguration extends WebMvcConfigurationSupport {

       @Override
      public void addFormatters(FormatterRegistry formatterRegistry) {
           formatterRegistry.addConverter(new MyConverter());
      }

      @Bean
      public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
           // Create or delegate to "super" to create and
           // customize properties of RequestMappingHandlerAdapter
      }
   }

所以无论是使用@EnableWebMvc还是WebMvcConfigurationSupport,都会禁止Spring Boot的自动装配@EnableAutoConfiguration中的设置( 虽然禁止了Spring boot的自动装配,但是WebMvcConfigurationSupport本身,还是会注册一系列的MVC相关的bean的)。

@EnableAutoConfiguration是SpringBoot项目的启动类注解@SpringBootApplication的子元素,@EnableAutoConfiguration实际是导入EnableAutoConfigurationImportSelector和Registar两个类,主要功能是通过SpringFactoriesLoader.loadFactoryNames()导入jar下面配置文件META-INF/spring.factories。我们翻spring.factories,其中就包含WebMvc自动装配类:

...
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
...

并且@EnableAutoConfiguration 注解,会自动读取 application.properties 或 application.yml 文件中的配置。因此想想前面提到的第一个问题就很明白了。

如果想要使用自动配置生效,同时又要使用部分spring mvc默认配置的话,比如增加 viewController ,则可以将自己的配置类可以继承 WebMvcConfigurerAdapter 这个类。不过在Spring5.0版本WebMvcConfigurerAdapter 后这个类被标记为@Deprecated了 。

 * @author Rossen Stoyanchev
 * @since 3.1
 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
 * possible by a Java 8 baseline) and can be implemented directly without the
 * need for this adapter
 */
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
 ...
}

Spring 5.0后要使用Java8,而在Java8中接口是可以有default方法的,所以这个类就没必要了。所以我们只需要在自定义配置类中直接实现 WebMvcConfigurer 接口就好了

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("helloworld");
    }
}

When we access URL /hello then helloworld.jsp will run.

对于第二个问题,如果使用@EnableWebMvc了,那么就会自动覆盖了官方给出的/static, /public, META-INF/resources, /resources等存放静态资源的目录。

而将静态资源定位于src/main/webapp。当需要重新定义好资源所在目录时,则需要主动添加上述的那个配置类,来重写 addResourceHandlers方法。

@Configuration
@EnableWebMvc
public class MyWebConfig implements WebMvcConfigurer {
 @Override
 public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
            .addResourceLocations("classpath:/public/");
 }
}

从上述可知在SpringBoot中大多数时我们并不需要使用@EnableWebMvc注解,来看下官方的一段说明:

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

说明:

Spring Boot 默认提供Spring MVC 自动配置,不需要使用@EnableWebMvc注解

如果需要配置MVC(拦截器、格式化、视图等) 请使用添加@Configuration并实现WebMvcConfigurer接口.不要添加@EnableWebMvc注解。

@EnableWebMvc 只能添加到一个@Configuration配置类上,用于导入Spring Web MVC configuration

最后,如果Spring Boot在classpath里看到有 spring webmvc 也会自动添加@EnableWebMvc。

Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.

http://spring.io/guides/gs/rest-service/

@enablewebmvc注解有什么用途

@EnableWebMvc是使用Java 注解快捷配置Spring Webmvc的一个注解。在使用该注解后配置一个继承于WebMvcConfigurerAdapter的配置类即可配置好Spring Webmvc。

通过查看@EnableWebMvc的源码,可以发现该注解就是为了引入一个DelegatingWebMvcConfiguration Java 配置类。并翻看DelegatingWebMvcConfiguration的源码会发现该类似继承于WebMvcConfigurationSupport的类。

其实不使用@EnableWebMvc注解也是可以实现配置Webmvc,只需要将配置类继承于WebMvcConfigurationSupport类即可

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解使用Spring快速创建web应用的两种方式

    介绍 本篇文章主要介绍,如何使用 Spring 开发一个 Web 应用. 我们将研究用 Spring Boot 开发一个 web 应用,并研究用非 Spring Boot 的方法. 我们将主要使用 Java 配置,但还要了解它们的等效的 XML 配置. 使用 Spring Boot Maven 依赖 首先,我们需要引用 spring-boot-starter-web 依赖: <dependency> <groupId>org.springframework.boot</gro

  • Spring Web MVC框架学习之配置Spring Web MVC

    这一篇文章讲的是Spring Web MVC各部分的配置方法,包括Java代码配置和XML文件配置以及MVC命名空间的使用方法. 启用MVC Java配置和XML命名空间 默认配置 要启用MVC Java配置(@Controller等各种注解)和XML命名空间,如果使用的是Java配置,在配置类上再添加@EnableWebMvc注解即可. @Configuration @EnableWebMvc public class WebAppConfig { } 如果使用XML配置文件的话,添加下面一行

  • Spring @Enable模块驱动原理及使用实例

    Spring @Enable 模块概览 框架实现 @Enable注解模块 激活模块 Spring Framework @EnableWebMvc Web MVC 模块 @EnableTransactionManagement 事务管理模块 @EnableCaching Caching 模块 @EnableMBeanExport JMX 模块 @EnableAsync 异步处理模块 @EnableWebFlux Web Flux 模块 @EnableAspectJAutoProxy AspectJ

  • Spring MVC完全注解方式配置web项目

    在servlet 3.0 开始web项目可以完全不需要web.xml配置文件了,所以本文的配置只在支持servlet 3.0及以上的web容器中有效 使用的是spring mvc (4.3.2.RELEASE) + thymeleaf(3.0.2.RELEASE), 持久层使用的 spring的 JdbcTemplate, PS:推荐一个很好用的对JdbcTemplate封装的框架:https://github.com/selfly/dexcoder-assistant  . 下面开始具体的配置

  • Spring注解@EnableWebMvc使用的坑点及解析

    目录 Spring注解@EnableWebMvc使用坑点 @enablewebmvc注解有什么用途 Spring注解@EnableWebMvc使用坑点 通过注解的方式来进行Spring4 MVC开发时,我们都会在配置文件中加入<mvc:annotation-driven/>标签,这个配置会自动注册了一个 RequestMappingHandlerMapping.一个RequestMappingHandlerAdapter.以及一个ExceptionHandlerExceptionResolve

  • Spring注解 TX声明式事务实现过程解析

    环境搭建导入 maven依赖 <!--spring提供的数据库操作工具--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!--c3p0 数据库连接池--> &

  • 详解 Spring注解的(List&Map)特殊注入功能

    详解 Spring注解的(List&Map)特殊注入功能 最近接手一个新项目,已经没有原开发人员维护了.项目框架是基于spring boot进行开发.其中有两处Spring的注解花费了大量的时间才弄明白到底是怎么用的,这也涉及到spring注解的一个特殊的注入功能. 首先,看到代码中有直接注入一个List和一个Map的.示例代码如下: @Autowired private List<DemoService> demoServices; @Autowired private Map<

  • Java之Spring注解配置bean实例代码解析

    前面几篇均是使用xml配置bean,如果有上百个bean,这是不可想象的.故而,请使用注解配置bean !!! [1]注解类别 @Component : 基本注解, 标识了一个受 Spring(点击这里可以下载<Spring应用开发完全手册>) 管理的组件 @Repository : 标识持久层组件 @Service : 标识服务层(业务层)组件 @Controller : 标识表现层组件 Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件. 对于扫描到的组

  • spring注解识别一个接口的多个实现类方法

    1.比如有一个接口如下: public interface Filter { public String doFilter(String param); } 2.有如下接口实现类: public class TimeFilter implements Filter { @Override public String doFilter(String param) { return param.replace("aa", "bb"); } }  3.使用方式:在接口实现

  • 详解Spring注解--@Autowired、@Resource和@Service

    什么是注解 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文件,那么.xml文件又会非常多.总之这将导致配置文件的可读性与可维护性变得很低 2.在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率 为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java

  • Spring 注解编程模型相关知识详解

    Spring 中有一个概念叫「元注解」(Meta-Annotation),通过元注解,实现注解的「派生性」,官方的说法是「Annotation Hierarchy」. 什么是元注解 所谓元注解,即标注在注解上的注解.这种方式所形成的注解层级结构中,元注解在层级结构的上面,我叫它父注解(Super Annotation), 被注解的注解在层级结构的下面,叫它子注解(Sub Annotation).引入元注解的目的是为了实现属性重写(Attribute Override) 的目的. 举个简单的例子:

  • Spring注解@RestControllerAdvice原理解析

    这篇文章主要介绍了Spring注解@RestControllerAdvice原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice.现在把此注解的用法总结一下. 用法 首先定义返回对象ResponseDto package com.staff.points.common; import lombok.Data;

  • Spring注解和同步锁不能同步问题解决

    这篇文章主要介绍了Spring注解和同步锁不能同步问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 结论:如果在service层的方法上同时使用事务和同步锁无法保证数据同步. @Service public class ServiceImpl{ private static Lock lock = new ReentrantLock(false); @Transactional(rollbackFor = Exception.class)

  • 深入理解Spring注解@Async解决异步调用问题

    序言:Spring中@Async 根据Spring的文档说明,默认采用的是单线程的模式的.所以在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的. 那么当多个任务的执行势必会相互影响.例如,如果A任务执行时间比较长,那么B任务必须等到A任务执行完毕后才会启动执行.又如在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring3.x之后,已经内置了@Async来完美解决这个问题. 1. 何为异步调用? 在解释之前,我们先来看二

随机推荐