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;
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfiguration.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfiguration.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter("UTF-8", true);
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;
@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 {
@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;
@Configuration
@EnableWebMvc
@ComponentScan(value = {"edu.whut.springbear.gather.controller"})
public class SpringMvcConfiguration implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@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");
}
@Bean
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
@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;
@Configuration
public class MyBatisConfiguration {
@Bean("sqlSessionFactory")
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("edu.whut.springbear.gather.pojo");
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;
}
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("edu.whut.springbear.gather.mapper");
return mapperScannerConfigurer;
}
@Bean
public PageInterceptor getPageInterceptor() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("value", "true");
pageInterceptor.setProperties(properties);
return pageInterceptor;
}
}
5、结语
至此,注解方式整合 SSM 常用配置基本完成,剩下的基本就是编写业务代码处理自己的业务逻辑,不再赘述。可参考个人全注解 SSM 开源项目【两码一查】
|