Spring MVC 十一:@EnableWebMvc

news2024/11/27 2:26:50

我们从两个角度研究@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 十一:中文乱码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1092595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hermes - 指尖上的智慧:自定义问答系统的崭新世界

在希腊神话中&#xff0c;有一位智慧与消息的传递者神祇&#xff0c;他就是赫尔墨斯&#xff08;Hermes&#xff09;。赫尔墨斯是奥林匹斯众神中的一员&#xff0c;传说他是乌尔阿努斯&#xff08;Uranus&#xff09;和莫伊拉&#xff08;Maia&#xff09;的儿子&#xff0c;同…

【Java 进阶篇】JavaScript Math对象详解

在JavaScript编程中&#xff0c;Math对象是一个非常有用的工具&#xff0c;用于执行各种数学运算。它提供了许多数学函数和常数&#xff0c;可以用于处理数字、执行几何运算、生成随机数等。在本篇博客中&#xff0c;我们将深入探讨JavaScript中Math对象的各种功能和用法。 什…

城市广告牌安全传感器特点有哪些?

城市广告牌安全传感器特点有哪些&#xff1f; 在现代快节奏的都市生活中&#xff0c;城市的广告牌成为不可或缺的一部分&#xff0c;以各种形式和大小存在于城市的街头巷尾&#xff0c;商业中心和交通要道。广告牌是城市生命线组成的一部分。但是由于天气因素、材料老化、不当维…

C++智能指针(三)——unique_ptr初探

与共享指针shared_ptr用于共享对象的目的不同&#xff0c;unique_ptr是用于独享对象。 文章目录 1. unqiue_ptr的目的2. 使用 unique_ptr2.1 初始化 unique_ptr2.2 访问数据2.3 作为类的成员2.4 处理数组 3. 转移所有权3.1 简单语法3.2 函数间转移所有权3.2.1 转移至函数体内3.…

VS Code:CMake配置

概述 在VSCode和编译器MinGW安装完毕后&#xff0c;要更高效率的进行C/C开发&#xff0c;采用CMake。CMake是一个开源、跨平台的编译、测试和打包工具&#xff0c;它使用比较简单的语言描述编译&#xff0c;安装的过程&#xff0c;输出Makefile或者project文件&#xff0c;再去…

【JavaEE】 饿汉模式与懒汉模式详解与实现

文章目录 &#x1f334;单例模式&#x1f340;饿汉模式&#x1f38d;懒汉模式&#x1f6a9;单线程版(线程不安全&#xff09;&#x1f6a9;多线程版&#x1f6a9;多线程版(改进) ⭕总结 &#x1f334;单例模式 单例模式是校招中最常考的设计模式之一. 那么啥是设计模式呢? 设…

五子棋(C语言实现)

目录 构思 1、主程序 2、初始化 3、游戏菜单 4、打印棋盘 6、玩家下棋 7、判断输赢 8、功能整合 人机下棋 完整版&#xff1a; game.h game.c text.c 测试功能代码 构思 五子棋不必多介绍了&#xff0c;大家小时候都玩过哈。 我们要通过程序实现这个小游戏&…

AI对网络安全的影响与挑战

近年来&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;网络安全领域也开始逐渐引入生成式AI应用。根据最新的数据研究&#xff0c;生成式AI对网络安全和合规的影响最大&#xff0c;同时也包括了IT和云的运维、硬件和软件支持领域。通过AI和自动…

Typora--博客必备神器

文章目录 一、下载typora二、创建文件前的操作1.显示扩展名2.typora设置和markdown语法2.1markdown语法2.2图片的管理2.3**高亮**2.4设置自动保存和调试 一、下载typora 进入typota.io网站&#xff0c;点击下载即可。 二、创建文件前的操作 1.显示扩展名 设置显示文件扩展名…

python+django学生选课管理系统_wxjjv

1&#xff09;前台&#xff1a;首页、课程信息、校园论坛、校园公告、个人中心、后台管理。 &#xff08;2&#xff09;管理员&#xff1a;首页、个人中心、学生管理、教师管理课、程信息管理、课程分类管理、选课信息管理、作业信息管理、提交作业管理、学生成绩管理、校园论…

android studio 移植工程

第一步&#xff1a; 第二步&#xff1a;创建 第三步&#xff1a; 第四步&#xff1a;复制文件至替代新工程中的文件 第五步&#xff1a;修改 第六步&#xff1a;编译OK

第 125 场周赛 三元组

可恶&#xff0c;被longlong的长度卡住了&#xff0c;要是longlong再大一点就好了&#xff08;bushi&#xff09;&#xff0c;其实是算法有问题&#xff0c;里面涉及1e9*1e9*1e9,longlong肯定存不下&#xff0c;一会儿去改改&#xff0c;先记录一下。 题目&#xff1a;竞赛 - …

树莓派玩转openwrt软路由:12.OpenWrt安装MySQL

1、安装MySQL #下载MySQL镜像 docker pull arm64v8/mysql:latest#运行MySQL镜像 docker run --name mysql --restartalways --privilegedtrue \ -v /usr/local/mysql/data:/var/lib/mysql \ -v /usr/local/mysql/conf.d:/etc/mysql/conf.d \ -e MYSQL_ROOT_PASSWORD123456 -p …

C++——C++入门

C 前言一、认识C二、C入门C关键字(C98)命名空间命名空间定义命名空间使用 C输入&输出缺省参数缺省参数概念缺省参数分类 函数重载函数重载概念C支持函数重载的原理--名字修饰(name Mangling) 总结 前言 C的学习开始啦&#xff01; 来吧~让我们拥抱更广阔的知识海洋&#x…

msvcp140.dll文件下载方法,找不到msvcp140.dll丢失的解决方法

在我日常的计算机维护和故障排除工作中&#xff0c;我遇到了许多由于丢失或损坏MSVCP140.dll文件而导致的程序无法正常运行的问题。这个DLL文件是Microsoft Visual C 2010 Redistributable Package的一部分&#xff0c;它是许多Windows应用程序&#xff08;尤其是使用C编写的程…

C++11中类与对象推出的新功能 [补充讲解final/override关键字]

文章目录 1.移动构造2.移动赋值对于移动构造/移动赋值的想法 3.类成员定义时初始化4.强制生成默认函数的关键字default5.禁止生成默认函数的关键字delete5.1介绍5.2应用场景1.法一:析构函数私有化2.法二: delete关键字思考 6.final关键字7.override关键字 1.移动构造 编译器自动…

Lambda表达式(JAVA)

注&#xff1a;如果没有学过匿名内部类和接口不推荐往下看。 Lambda表达式的语法&#xff1a; (parameters) -> expression 或 (parameters) ->{ statements; } parameters&#xff1a;表示参数列表&#xff1b;->&#xff1a;可理解为“被用于”的意思&#xff1b…

苹果修复了旧款iPhone上的iOS内核零日漏洞

导语 近日&#xff0c;苹果发布了针对旧款iPhone和iPad的安全更新&#xff0c;回溯了一周前发布的补丁&#xff0c;解决了两个被攻击利用的零日漏洞。这些漏洞可能导致攻击者在受影响的设备上提升权限或执行任意代码。本文将介绍这些漏洞的修复情况以及苹果在修复漏洞方面的持续…

自定义类型:结构体,枚举,联合 (2)

2. 位段 位段的出现就是为了节省空间。 2.1 什么是位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 1.位段的成员必须是 int、unsigned int 或signed int 。 2.位段的成员名后边有一个冒号和一个数字。 比如&#xff1a; struct A {int _a:2;int _b:5;int…

ArcGIS笔记5_生成栅格文件时保存报错怎么办

本文目录 前言Step 1 直接保存到指定文件夹会报错Step 2 先保存到默认位置再数据导出到指定文件夹 前言 有时生成栅格文件时&#xff0c;保存在自定义指定的文件夹内会提示出错&#xff0c;而保存到默认位置则没有问题。因此可以通过先保存到默认位置&#xff0c;再数据导出到…