SpringMVC的全注解开发
Posted Super_Leng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC的全注解开发相关的知识,希望对你有一定的参考价值。
文章目录
一、spring-mvc.xml 中组件转化为注解形式
跟之前全注解开发思路一致, xml配置文件使用核心配置类替代,xml中的标签使用对应的注解替代
<!-- 组件扫描web层 -->
<context:component-scan base-package="com.itheima.controller"/>
<!--注解驱动-->
<mvc:annotation-driven/>
<!--配置文件上传解析器-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.itheima.interceptor.MyInterceptor01"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--配置DefaultServletHttpRequestHandler-->
<mvc:default-servlet-handler/>
⚫ 组件扫描,可以通过@ComponentScan注解完成;
⚫ 文件上传解析器multipartResolver可以通过非自定义Bean的注解配置方式,即@Bean注解完成
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMVCConfig
@Bean
public CommonsMultipartResolver multipartResolver()
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("UTF-8");
multipartResolver.setMaxUploadSize(3145728);
multipartResolver.setMaxUploadSizePerFile(1048576);
multipartResolver.setMaxInMemorySize(1048576);
return multipartResolver;
< mvc:annotation-driven>、< mvc:default-servlet-handler /> 和 < mvc:interceptor > 怎么办呢?SpringMVC 提供了一个注解@EnableWebMvc,我们看一下源码,内部通过@Import 导入了DelegatingWebMvcConfiguration类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 从容器中注入WebMvcConfigurer类型的Bean
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers)
if (!CollectionUtils.isEmpty(configurers))
this.configurers.addWebMvcConfigurers(configurers);
//省略其他代码
WebMvcConfigurer类型的Bean会被注入进来,然后被自动调用,所以可以实现WebMvcConfigurer接口,完成一些解析器、默认Servlet等的指定,WebMvcConfigurer接口定义如下:
public interface WebMvcConfigurer
// 配置默认Servet处理器
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
// 添加拦截器
default void addInterceptors(InterceptorRegistry registry)
// 添加资源处理器
default void addResourceHandlers(ResourceHandlerRegistry registry)
// 添加视图控制器
default void addViewControllers(ViewControllerRegistry registry)
// 配置视图解析器
default void configureViewResolvers(ViewResolverRegistry registry)
// 添加参数解析器
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)
// ... 省略其他代码 ...
创建MyWebMvcConfigurer实现WebMvcConfigurer接口,实现addInterceptors 和 configureDefaultServletHandling方法
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
// 开启DefaultServlet,可以处理静态资源了
configurer.enable();
@Override
public void addInterceptors(InterceptorRegistry registry)
// 创建拦截器对象,进行注册
// Interceptor的执行顺序也取决于添加顺序
registry.addInterceptor(new MyInterceptor01()).addPathPatterns("/*");
最后,在SpringMVC核心配置类上添加@EnableWebMvc注解
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMVCConfig
@Bean
public CommonsMultipartResolver multipartResolver()
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("UTF-8");
multipartResolver.setMaxUploadSize(3145728);
multipartResolver.setMaxUploadSizePerFile(1048576);
multipartResolver.setMaxInMemorySize(1048576);
return multipartResolver;
二、DispatcherServlet加载核心配置类
DispatcherServlet在进行SpringMVC配置文件加载时,使用的是以下方式:
<!--配置springMVC前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定springMVC配置文件位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--服务器启动就创建-->
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
现在是使用SpringMVCConfig核心配置类替代的spring-mvc.xml,怎么加载呢?参照Spring的ContextLoaderListener加载核心配置类的做法,定义了一个AnnotationConfigWebApplicationContext,通过代码注册核心配置类
public class MyAnnotationConfigWebApplicationContext extends AnnotationConfigWebApplicationContext
public MyAnnotationConfigWebApplicationContext()
// 注册核心配置类
super.register(SpringMVCConfig.class);
<!--指定springMVC的applicationContext全限定名 -->
<init-param>
<param-name>contextClass</param-name>
<param-value>com.itheima.config.MyAnnotationConfigWebApplicationContext</param-value>
</init-param>
三、消除web.xml
目前,几乎消除了配置文件,但是web工程的入口还是使用的web.xml进行配置的,如下:
<!--配置springMVC前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定springMVC的applicationContext全限定名 -->
<init-param>
<param-name>contextClass</param-name>
<param-value>com.itheima.config.MyAnnotationConfigWebApplicationContext</param-value>
</init-param>
<!--服务器启动就创建-->
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
⚫ Servlet3.0环境中,web容器提供了javax.servlet.ServletContainerInitializer接口,实现了该接口后,在对应的类加载路径的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作;
⚫ 基于这个特性,Spring就定义了一个SpringServletContainerInitializer实现了ServletContainerInitializer接口;
⚫ 而SpringServletContainerInitializer会查找实现了WebApplicationInitializer的类,Spring又提供了一个WebApplicationInitializer的基础实现类AbstractAnnotationConfigDispatcherServletInitializer,当我们编写类继承AbstractAnnotationConfigDispatcherServletInitializer时,容器就会自动发现我们自己的类,在该类中我们就可以配置Spring和SpringMVC的入口了。
按照下面的配置就可以完全省略web.xml
public class MyAnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
// 返回的带有@Configuration注解的类用来配置ContextLoaderListener
protected Class<?>[] getRootConfigClasses()
System.out.println("加载核心配置类创建ContextLoaderListener");
return new Class[]ApplicationContextConfig.class;
// 返回的带有@Configuration注解的类用来配置DispatcherServlet
protected Class<?>[] getServletConfigClasses()
System.out.println("加载核心配置类创建DispatcherServlet");
return new Class[]SpringMVCConfig.class;
// 将一个或多个路径映射到DispatcherServlet上
protected String[] getServletMappings()
return new String[]"/";
SpringSpringMVCMyBatis 的全注解方式整合
文章目录
1、引语
-
在学习注解方式整合 SSM 框架之前,一定要先学会 xml 配置文件整合(SSM 框架整合)
-
所谓使用全注解的方式进行 SSM 整合开发,就需要自定义类来替代 Spring、SpringMVC、MyBatis 的核心 xml 配置文件以及 web.xml,那么这些自定义的类 Tomcat 怎么就能知道他们用于配置框架的呢?就得从 web.xml 的替代配置类中入手分析
-
在 Servlet3.0 环境中,Tomcat 会在类路径中查找
javax.servlet.ServletContainerInitializer
接口的实现类,如果找到就用该类来配置 Servlet 容器 -
在 Spring 中提供了这个接口的实现,名为
SpringServletContainerInitializer
,这个类反过来又会查找WebApplicationInitializer
接口的实现类并将配置的任务交给WebApplicationInitializer
的实现类来完成 -
而 Spring3.2 及以上版本引入了一个便利的 WebApplicationInitializer 接口的基础实现类
AbstractAnnotationConfigDispatcherServletInitializer
(没错,类名就是这么长),当我们的类继承了 AbstractAnnotationConfigDispatcherServletInitializer 并将其部署到 Servlet3.0 容器的时候,容器会自动发现它,并用它来配置 Servlet 上下文容器
由以上分析,使用全注解的方式配置 SSM,有以下几个核心步骤:
- 自定义类来继承
AbstractAnnotationConfigDispatcherServletInitializer
类以替代 web.xml,并在其中指定 Spring、SpringMVC 的配置类,指定 DispatcherServlet 的拦截路径,配置编码过滤器等- 自定义类配置 Spring,容器如何知道这是一个配置类呢?Spring 为我们提供了一个便捷的注解
@Configuration
,使用该注解标识一个类,容器就会将该类标识一个配置类并加载其中的配置- 同理可自定义类来配置 SpringMVC、MyBatis(可直接在 Spring 的配置类中配置,此处为方便理解将其用单独的配置类进行配置)
1、web.xml 的替代配置类
package edu.whut.springbear.gather.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
/**
* web.xml 的替代配置类
*
* @author Spring-_-Bear
* @datetime 2022-06-30 14:35 Thursday
*/
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
/**
* 指定 Spring 的配置类
*/
@Override
protected Class<?>[] getRootConfigClasses()
return new Class[]SpringConfiguration.class;
/**
* 指定 SpringMVC 的配置类
*/
@Override
protected Class<?>[] getServletConfigClasses()
return new Class[]SpringMvcConfiguration.class;
/**
* 指定 DispatchServlet 的拦截路径
*/
@Override
protected String[] getServletMappings()
return new String[]"/";
/**
* 过滤器
*/
@Override
protected Filter[] getServletFilters()
// 编码过滤器解决中文乱码
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter("UTF-8", true);
// Http 请求方法过滤器以支持 RESTful 风格编程
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]characterEncodingFilter, hiddenHttpMethodFilter;
2、Spring 的配置类
- 使用
@Import
注解可引入其它的配置类如 MyBatis 的配置类 - 使用
@PropertySource
注解可引入 .properties 配置文件如引入数据库配置文件 - 使用
@ComponentScan
注解扫描包中的组件(一定不要扫描 Spring 配置类所在的包,否则报错),组件扫描的策略是:除了 Controller 组件留给 SpringMVC 扫描,其余组件均有 Spring 扫描。言外之意就是 Spring 处理不扫描 controller 包,其余所有包均可扫描(不可以同时在 Spring 和 SpringMVC 中扫描 controller 包,否则报错=)
package edu.whut.springbear.gather.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
/**
* Spring 的配置类以替代 applicationContext.xml
*
* @author Spring-_-Bear
* @datetime 2022-06-30 14:36 Thursday
*/
@Configuration
@Import(MyBatisConfiguration.class)
@PropertySource("classpath:application.properties")
@ComponentScan(basePackages = "edu.whut.springbear.gather.pojo", "edu.whut.springbear.gather.mapper",
"edu.whut.springbear.gather.service", "edu.whut.springbear.gather.util",
"edu.whut.springbear.gather.exception", "edu.whut.springbear.gather.interceptor")
public class SpringConfiguration
/**
* 读取 application.properties 中的配置信息
*/
@Value("$jdbc.url")
private String url;
@Value("$jdbc.driver")
private String driver;
@Value("$jdbc.username")
private String username;
@Value("$jdbc.password")
private String password;
/**
* 配置数据源
*/
@Bean
public DataSource getDataSource()
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
3、SpringMVC 的配置类
- 使用
@EnableWebMVC
注解开启注解驱动以支持 SpringMVC 的一些高级功能 - 使用
@ComponentScan
注解扫描 controller 组件 - 在 SpringMVC 的配置类中配置一些常用的组件如:默认 Servlet 处理静态资源、Thymeleaf 视图解析器、视图控制器实现、文件上传解析器、拦截器等
package edu.whut.springbear.gather.config;
import edu.whut.springbear.gather.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
/**
* SpringMVC 的配置类
*
* @author Spring-_-Bear
* @datetime 2022-06-30 14:36 Thursday
*/
@Configuration
@EnableWebMvc
@ComponentScan(value = "edu.whut.springbear.gather.controller")
public class SpringMvcConfiguration implements WebMvcConfigurer
/**
* 配置默认 Servlet 处理静态资源
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
configurer.enable();
/**
* 以下三个方法均用于配置 Thymeleaf 视图解析器
* ITemplateResolver -> SpringTemplateEngine -> ViewResolver
*/
@Bean
public ITemplateResolver templateResolver()
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
assert webApplicationContext != null;
ServletContext servletContext = webApplicationContext.getServletContext();
assert servletContext != null;
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
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;
/**
* 视图控制器(不需要处理逻辑,仅仅实现页面跳转时使用)
*/
@Override
public void addViewControllers(ViewControllerRegistry registry)
registry.addViewController("/").setViewName("index");
/**
* 文件上传解析器:需要引入 commons-fileupload 依赖
*/
@Bean
public CommonsMultipartResolver multipartResolver()
return new CommonsMultipartResolver();
/**
* 拦截器:需要自定义类实现 HandlerInterceptor 接口
*/
@Override
public void addInterceptors(InterceptorRegistry registry)
// 登录拦截器:拦截除 / 首页外的所有请求
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/");
4、MyBatis 的配置类
在 MyBatis 的配置类设置数据源并配置一些常用的功能,如:以包为单位为 POJO 类设置别名、开启自动驼峰命名转换、设置分页插件等
package edu.whut.springbear.gather.config;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Properties;
/**
* MyBatis 的配置类
*
* @author Spring-_-Bear
* @datetime 2022-06-30 15:07 Thursday
*/
@Configuration
public class MyBatisConfiguration
/**
* SQL 会话工厂
*/
@Bean("sqlSessionFactory")
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource)
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 设置数据源
sqlSessionFactoryBean.setDataSource(dataSource);
// 以包为单位设置 POJO 类别名(默认为类名)
sqlSessionFactoryBean.setTypeAliasesPackage("edu.whut.springbear.gather.pojo");
// 开启自动驼峰命名转换(Java 成员变量与数据库表字段之间的自动转换)
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
sqlSessionFactoryBean.setConfiguration(configuration);
// 设置分页插件
sqlSessionFactoryBean.setPlugins(new Interceptor[]getPageInterceptor());
return sqlSessionFactoryBean;
/**
* 指定 Mapper 接口所在的包
*/
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer()
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("edu.whut.springbear.gather.mapper");
return mapperScannerConfigurer;
/**
* 设置分页插件:需引入 com.github.pagehelper 依赖
*/
@Bean
public PageInterceptor getPageInterceptor()
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("value", "true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
5、结语
至此,注解方式整合 SSM 常用配置基本完成,剩下的基本就是编写业务代码处理自己的业务逻辑,不再赘述。可参考个人全注解 SSM 开源项目【两码一查】
以上是关于SpringMVC的全注解开发的主要内容,如果未能解决你的问题,请参考以下文章