SpringMvc+Spring+MyBatis 基于注解整合
最近在给学生们讲 Spring+Mybatis 整合,根据有的学生反映还是基于注解实现整合便于理解,毕竟在先前的工作中团队里还没有人完全舍弃配置文件进行项目开发,由于这两个原因,我索性参考 spring 官方文档研究出完全基于注解整合 ssm 框架。毕竟无配置化也是 Spring 官方所推行的,要不 SpringBoot 存在的意义为何嘛
一。整合思路
1)目标:毫无保留的将配置文件的所有配置项改变注解加创建对象的方式实现
2)Spring 提供的 @Bean @Configuration @ComponentScan @EnableTransactionManagement @EnableWebMvc 等 需要知道其含义
二。创建 spring-mvc 的 web 项目
1) 项目结构目录:
在这里 web.xml 里不写任何配置
三。在 config 包下分别创建配置类与属性文件
1. AppConfig.java
package com.bdqn.lyrk.ssm.study.app;import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;
import java.io.IOException;/**
spring 的配置类
@author chen.nie
@date 2018/6/24
/
@Configuration //表明此类是配置类
@ComponentScan // 扫描自定义的组件 (repository service component controller)
@PropertySource("classpath:application.properties") // 读取 application.properties
@MapperScan("com.bdqn.lyrk.ssm.study.app.mapper") //扫描 Mybatis 的 Mapper 接口
@EnableTransactionManagement //开启事务管理
public class AppConfig {/**
- 配置数据源
- @date 2018/6/24
/
@Bean
public DataSource dataSource(PropertiesConfig propertiesConfig) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(propertiesConfig.getUserName());
dataSource.setPassword(propertiesConfig.getPassword());
dataSource.setUrl(propertiesConfig.getUrl());
dataSource.setDriverClassName(propertiesConfig.getDriverClass());
return dataSource;
}/**
配置 mybatis 的 SqlSessionFactoryBean
@param dataSource
@param propertiesConfig
@return
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource, PropertiesConfig propertiesConfig) throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage(propertiesConfig.getMybatisTypeAliasPackages());
// 动态获取 SqlMapper
PathMatchingResourcePatternResolver classPathResource = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(classPathResource.getResources(propertiesConfig.getMapperLocations()));return sqlSessionFactoryBean;
}/**
- 配置 spring 的声明式事务
- @return
*/@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);
return dataSourceTransactionManager;}
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
return propertySourcesPlaceholderConfigurer;
}}
没什么好说的,这里主要创建 Spring 与 Mybatis 整合的相关对象以及声明式事务切面,我们把配置文件中的东西通通用 java 代码创建,注意 @Bean 注解的使用
2.DispatcherConfig
1 package com.bdqn.lyrk.ssm.study.config; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.web.servlet.config.annotation.EnableWebMvc; 7 import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 9 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 10 import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; 11 import org.springframework.web.servlet.view.InternalResourceViewResolver; 12 import org.springframework.web.servlet.view.JstlView; 13 14 import java.util.Properties; 15 16 @Configuration 17 @EnableWebMvc 18 public class DispatcherConfig extends WebMvcConfigurerAdapter { 19 20 21 @Autowired 22 private PropertyConfig propertyConfig; 23 24 @Bean 25 public InternalResourceViewResolver internalResourceViewResolver() { 26 InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver(); 27 internalResourceViewResolver.setViewClass(JstlView.class); 28 internalResourceViewResolver.setPrefix(propertyConfig.getWebViewPrefix()); 29 internalResourceViewResolver.setSuffix(propertyConfig.getWebViewSuffix()); 30 return internalResourceViewResolver; 31 } 32 33 /** 34 * 设置统一错误处理要跳转的视图 35 * 36 * @return 37 */ 38 @Bean 39 public SimpleMappingExceptionResolver simpleMappingExceptionResolver() { 40 SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver(); 41 Properties properties = new Properties(); 42 properties.getProperty("java.lang.Exception", "error"); 43 simpleMappingExceptionResolver.setExceptionMappings(properties); 44 return simpleMappingExceptionResolver; 45 } 46 47 /** 48 * 添加静态资源 49 * 50 * @param registry 51 */ 52 @Override 53 public void addResourceHandlers(ResourceHandlerRegistry registry) { 54 registry.addResourceHandler(propertyConfig.getWebStaticHandler()).addResourceLocations(propertyConfig.getWebStaticResource()).setCachePeriod(propertyConfig.getWebStaticCachedPeriod()); 55 } 56 57 /** 58 * 添加拦截器 59 * 60 * @param registry 61 */ 62 @Override 63 public void addInterceptors(InterceptorRegistry registry) { 64 super.addInterceptors(registry); 65 } 66 }
此处配置 SpringMVC 的视图解析器,静态资源等,依旧照搬配置文件中的代码
3.PropertiesConfig
package com.bdqn.lyrk.ssm.study.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;@Configuration
@PropertySource("classpath:application.properties")
public class PropertyConfig {@Value(</span>"${spring.datasource.url}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String url; @Value(</span>"${spring.datasource.driver}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String driver; @Value(</span>"${spring.datasource.user}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String user; @Value(</span>"${spring.datasource.password}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String password; @Value(</span>"${spring.web.view.prefix}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String webViewPrefix; @Value(</span>"${spring.web.view.suffix}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String webViewSuffix; @Value(</span>"${spring.web.static.handler}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String webStaticHandler; @Value(</span>"${spring.web.static.resource}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String webStaticResource; @Value(</span>"${spring.web.static.cache.period}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Integer webStaticCachedPeriod; @Value(</span>"${mybatis.type.alias.package}"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String mybatisTypeAliasPackage; </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getWebViewPrefix() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webViewPrefix; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getWebViewSuffix() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webViewSuffix; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getWebStaticHandler() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webStaticHandler; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getWebStaticResource() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webStaticResource; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> Integer getWebStaticCachedPeriod() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> webStaticCachedPeriod; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getMybatisTypeAliasPackage() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mybatisTypeAliasPackage; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getUrl() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> url; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getDriver() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> driver; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getUser() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> user; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getPassword() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> password; } @Bean </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PropertySourcesPlaceholderConfigurer(); }
}
此处用于读取 application.properties 的文件内容 注意 @Value 与 @PropertySource 的含义
4.MyWebAppInitializer
1 package com.bdqn.lyrk.ssm.study.config; 2 3 import org.springframework.web.filter.CharacterEncodingFilter; 4 import org.springframework.web.servlet.DispatcherServlet; 5 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 6 7 import javax.servlet.Filter; 8 import javax.servlet.ServletContext; 9 import javax.servlet.ServletException; 10 11 /** 12 * 初始化 servlet WebApplicationContext 相关 13 * 14 * @author chen.nie 15 * @date 2017/12/28 16 **/ 17 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 18 19 @Override 20 protected Class<?>[] getRootConfigClasses() { 21 return new Class[]{AppConfig.class}; 22 } 23 24 @Override 25 protected Class<?>[] getServletConfigClasses() { 26 return new Class[]{DispatcherServlet.class}; 27 } 28 29 @Override 30 protected String[] getServletMappings() { 31 return new String[]{"/"}; 32 } 33 34 35 /** 36 * 添加过滤器 37 * 38 * @return 39 */ 40 @Override 41 protected Filter[] getServletFilters() { 42 CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); 43 characterEncodingFilter.setEncoding("UTF-8"); 44 characterEncodingFilter.setForceEncoding(true); 45 return new Filter[]{characterEncodingFilter}; 46 } 47 }
在这里请大家关注一下这个类,这段代码的含义和配置 SpringMVC 的含义一样:
1 <web-app> 2 <context-param> 3 <param-name>contextConfigLocation</param-name> 4 <param-value>/WEB-INF/root-context.xml</param-value> 5 </context-param> 6 <servlet> 7 <servlet-name>dispatcher</servlet-name> 8 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 9 <init-param> 10 <param-name>contextConfigLocation</param-name> 11 <param-value></param-value> 12 </init-param> 13 <load-on-startup>1</load-on-startup> 14 </servlet> 15 <servlet-mapping> 16 <servlet-name>dispatcher</servlet-name> 17 <url-pattern>/</url-pattern> 18 </servlet-mapping> 19 <listener> 20 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 21 </listener> 22 </web-app>
5. application.properties
#数据库连接 spring.datasource.user=root spring.datasource.password=root spring.datasource.driver=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/MySchool?characterEncoding=utf-8&useSSL=false #web 设置相关 spring.web.view.prefix=/WEB-INF/jsp/ spring.web.view.suffix=.jsp spring.web.static.handler=/assets/** spring.web.static.resource=classpath:/assets/ spring.web.static.cache.period=360000 #mybatis 设置相关 mybatis.type.alias.package=com.bdqn.lyrk.ssm.study.entity
6. 创建 MyBatis 对应的 mapper
package com.bdqn.lyrk.ssm.study.mapper;import com.bdqn.lyrk.ssm.study.entity.StudentEntity;
import org.apache.ibatis.annotations.Select;import java.util.List;
public interface StudentMapper {
@Select(</span>"select * from Student"<span style="color: rgba(0, 0, 0, 1)">) List</span><StudentEntity><span style="color: rgba(0, 0, 0, 1)"> selectAll();
}
7. 创建业务逻辑
1 package com.bdqn.lyrk.ssm.study.service.impl; 2 3 import com.bdqn.lyrk.ssm.study.entity.StudentEntity; 4 import com.bdqn.lyrk.ssm.study.mapper.StudentMapper; 5 import com.bdqn.lyrk.ssm.study.service.IStudentService; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.stereotype.Service; 8 import org.springframework.transaction.annotation.Transactional; 9 10 import java.util.List; 11 12 @Service 13 public class StudentServiceImpl implements IStudentService { 14 @Autowired 15 private StudentMapper studentMapper; 16 17 18 @Override 19 public List<StudentEntity> selectAll() { 20 return studentMapper.selectAll(); 21 } 22 23 @Transactional 24 @Override 25 public int save(StudentEntity studentEntity) { 26 return 0; 27 } 28 29 30 }
8. 创建 Controller
package com.bdqn.lyrk.ssm.study.controller;import com.bdqn.lyrk.ssm.study.entity.StudentEntity;
import com.bdqn.lyrk.ssm.study.service.IStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;import java.util.List;
@Controller
public class IndexController {
@Autowired
private IStudentService studentService;@GetMapping(</span>"/index"<span style="color: rgba(0, 0, 0, 1)">) </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String index(ModelMap modelMap) { List</span><StudentEntity> list =<span style="color: rgba(0, 0, 0, 1)"> studentService.selectAll(); modelMap.put(</span>"students"<span style="color: rgba(0, 0, 0, 1)">, list); </span><span style="color: rgba(0, 0, 255, 1)">return</span> "index"<span style="color: rgba(0, 0, 0, 1)">; }
}
9.index.jsp 文件中内容
<%-- Created by IntelliJ IDEA. User: chen.nie Date: 2017/12/23 Time: 下午 8:40 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>$Title$</title> </head> <body> <c:forEach items="${students}" var="student"> ${student.stuName} </c:forEach> </body> </html>
10. 启动 tomcat 后访问 http://localhost:8080/portal/index 得到如下界面
OK!大功告成,注意前 4 步里面注解的运用,后面的步骤和往常的写法无异,想必大家都很熟悉了吧。