纯javaconfig搭建SSM工程
相信各位同用java的小伙伴对SSM传统的XML配置文件都是感觉挺麻烦的,而且不容易记忆。受广大开发者的需求,在Spring3时代,Spring推出了javaconfig,使得我们可以使用零XML的方式搭建Spring工程。而且Mybatis也可以完全使用注解开发(不过mybatis的xml方式也有他的优点)。因此,对于不喜欢使用XML配置的小伙伴们就可以完全摆脱XML的束缚,而是使用我们熟悉的java代码进行项目搭建。值得一提的是,在SpringBoot中也是大量使用javaconfig实现的自动装配。
环境要求:
- Spring 5 + Mybatis3
- Servlet3.0
- Java8+
一、web.xml的javaconfig
对于传统的java项目来说web.xml是必不可少的,他是程序的入口。然而从Servlet3.0开始,我们只需要实现WebApplicationInitializer接口,当你把实现类写好之后,Servlet 3.0可以自动发现它并对servlet进行初始化(当然也可以是多个实现类),可以说这个接口的实现类一定程度上等价于web.xml的配置。
Spring WebApplicationinitializer启动过程及原理分析
maven依赖
<!-- SpringMVC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- Servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
我们一般使用WebApplicationInitializer
的实现类AbstractAnnotationConfigDispatcherServletInitializer
来进行配置,配置如下:
public class SpringApplicationInitializer
extends AbstractAnnotationConfigDispatcherServletInitializer {
// Spring容器,相当于加载 applicationContext.xml
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class};
}
// servletContext, 相当于加载 springmvc.xml
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
// url-mapping
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//配置与Spring相关的Filter。这里规定Spring MVC的编码为UTF-8。
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] { characterEncodingFilter };
}
}
二、javaconfig配置Spring
/**
* Spring配置文件,主要用来配置Spring的Bean
*/
@EnableTransactionManagement
public class ApplicationConfig {
/**
* 读取配置文件
* @return
*/
@Bean
public PropertySourcesPlaceholderConfigurer getTestPpc() {
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
return ppc;
}
}
Spring的配置文件相对简单,主要配置的Spring的事务管理,其中PropertySourcesPlaceholderConfigurer
是在后面读取配置文件要用到的一个类,在Spring3以后被官方推荐使用。
三、javaconfig配置SpringMVC
在这里我使用了Spring官方建议的模板引擎thymeleaf,在配置过程中也是遇到了很多的坑。
thymeleaf需要引入如下maven依赖:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
@Configuration
@EnableWebMvc
@ComponentScan("top.vergessen")
public class WebConfig implements WebMvcConfigurer {
@Bean
public ClassLoaderTemplateResolver templateResolver(){
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("/static/");
templateResolver.setSuffix(".html");
// HTML是默认值, 为了清楚起见, 在此处添加
templateResolver.setTemplateMode(TemplateMode.HTML);
// 默认情况下, 模板缓存为true。如果您想要设置为false
templateResolver.setCacheable(true);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine自动应用SpringStandardDialect
// 并启用Spring自己的MessageSource消息解析机制。
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
/**
* Thymeleaf中的视图和视图分解器
*/
@Bean
public ViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
/**
* 路径映射 访问 /hello3 跳转到 hello
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello3").setViewName("hello.html");
}
/**
* 静态资源路径
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/img/**").addResourceLocations("/img/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
}
编写一个Controller实验一下:
@RestController
public class HelloController {
@GetMapping("/")
public ModelAndView hello(){
ModelAndView mod = new ModelAndView("hello");
mod.addObject("hello","Hello JavaConfig!");
return mod;
}
}
输出结果如下
使用到的静态页面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<div th:text="${hello}"></div>
</body>
</html>
四、javaconfig配置Mybatis
在这里我使用的是国产开源的Mybatis-plus
他是Mybatis的一个超集,完全适配原生Mybatis,并在Mybatis的基础上增加了免sql语句的单表增删改查,既保留了Mybatis的优点有提升了Mybatis的使用效率。
maven依赖:
<!--Mybatis-Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.3.1</version>
</dependency>
<!--Mysql jdbc驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- Spring jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!--阿里巴巴开源 druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
在这里我们使用了阿里的druid连接池
@PropertySource("classpath:jdbc.properties")
读取配置文件,使用@Value
注入数据
jdbc.properties:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm
jdbc.user=root
jdbc.password=root
@Configuration
@MapperScan("top.vergessen.mapper")
@PropertySource("classpath:jdbc.properties")
public class DaoConfig {
@Value("${jdbc.driverClass}")
private String driverClass;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.jdbcUrl}")
private String jdbcUrl;
@Bean
public DataSource dataSource() {
// 使用 druid 连接池
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setUrl(jdbcUrl);
return dataSource;
}
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
// 注意这里使用的是 MybatisSqlSessionFactoryBean(Mybatis-plus提供)
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
创建实体类Phone
@TableName("phone")
public class Phone {
@TableId
private long id;
private String brand;
private long price;
/* getter setter略,建议使用lombok */
}
创建Mapper,Mybatis-plus的Mapper接口需要继承BaseMapper,然后就可以获得MP提供的单表增删改查能力.
public interface PhoneMapper extends BaseMapper<Phone> {
}
在Controller中添加(为了演示方便,Service层就略去了):
@Autowired
private PhoneMapper phoneMapper;
@GetMapping("phone")
public List<Phone> getPhone(){
List<Phone> phoneList = phoneMapper.selectList(null);
phoneList.forEach(System.out::println);
return phoneList;
}
像上面代码一样我们直接返回java对象肯定是不行的,但是我们可以通过配置SpringMVC的消息转换器把返回的java对象自动转成JSON对象,以便于前端使用,为此我们需要引入fastjson
或者其他的JSON解析器
<!-- FastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
并在SpringMVC配置文件中添加如下代码:
/**
* JSON 配置 使返回的java对象自动转成JSON字符串
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
fastJsonConverter.setDefaultCharset(Charset.forName("UTF-8"));
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setCharset(Charset.forName("UTF-8"));
fastJsonConverter.setFastJsonConfig(fastJsonConfig);
converters.add(fastJsonConverter);
}
启动项目,运行,访问/phone(使用了Chrome的):
五、使用SpringMVC的拦截器
编写拦截器类:
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
System.err.println(requestURI + " 正在访问...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
String requestURI = request.getRequestURI();
System.err.println(requestURI + " 访问中...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String requestURI = request.getRequestURI();
System.err.println(requestURI + " 访问结束");
}
}
然后在SpringMVC中注册该拦截器:
/**
* 注册拦截器
*/
@Bean
public HandlerInterceptor handlerInterceptor(){
return new TestInterceptor();
}
/**
* 配置拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor())
.addPathPatterns("/**") // 拦截的路径
.excludePathPatterns("/"); // 不拦截的路径
}
访问/phone:
可以见到我们配置的拦截器在访问过程中的执行顺序
六、项目的运行环境
我是用的是IDEA运行本地的tomcat,配置如下:
我也有使用maven的tomcat插件,但是不知道为什么控制台打印输出的中文字符都是乱码,我进行字符集配置也没有生效,所以使用的本地tomcat进行的测试。
评论
添加一条评论