1.SSM介绍
Spring+SpringMVC+MyBatis
2.集成步骤
第二步和第三步哪个先集成顺序都无所谓
- Spring
- Spring+SpringMVC
- Spring+Mybtis
- Spring+SpringMVC+Mybatis:管理事务
3.jar的准备
模块名 | jar包 |
---|---|
Spring | com.springsource.org.apache.commons.logging-1.1.1.jar spring-aop-4.1.2.RELEASE.jar spring-beans-4.1.2.RELEASE.jar spring-context-4.1.2.RELEASE.jar spring-core-4.1.2.RELEASE.jar spring-expression-4.1.2.RELEASE.jar spring-test-4.1.2.RELEASE.jar |
SpringMVC | ① commons-fileupload-1.3.1.jar ② commons-io-2.2.jar ③ jackson-annotations-2.5.0.jar ④ jackson-core-2.5.0.jar ⑤ jackson-databind-2.5.0.jar ⑥ spring-web-4.1.2.RELEASE.jar ⑦ spring-webmvc-4.1.2.RELEASE.jar ①②文件上传③④⑤json转换⑥⑦springmvc |
MyBatis | asm-3.3.1.jar cglib-2.2.2.jar commons-logging-1.1.1.jar javassist-3.17.1-GA.jar log4j-1.2.17.jar mybatis-3.2.1.jar slf4j-api-1.7.2.jar slf4j-log4j12-1.7.2.jar |
Spring+MyBatis+事务 | ① com.springsource.org.aopalliance-1.0.0.jar ② com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar ③ com.springsource.org.apache.commons.pool-1.5.3.jar ④ com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar ⑤ spring-jdbc-4.1.2.RELEASE.jar ⑥ spring-tx-4.1.2.RELEASE.jar ①④⑥Aop事务②③⑤spring集成mybatis |
other | ①mybatis-spring-1.2.0.jar mysql-connector-java-5.1.26-bin.jar ①mybatis集成spring |
4.单独集成Spring
- 创建javaweb项目
- 导入spring的jar
- 准备配置文件applicationContext.xml并且配置对象
- 测试
- 能从spring中或bean
4.1 创建javaweb项目:
-
打开idea,点击New Project,点击Java Enterprise,选择jdk1.8,java EE8,tomcat 8.0,点击Next
-
勾选Create project from template,点击Next
2.png -
给项目起个名子,我这里叫 SSM
3.png -
项目创建成功,配置jsp有改动会主动应用.点击Edit Configurations-->Tomcat Server-->On 'Update' action选择Update classes and resources并且On frame deactivation选择Update classes and resources-->Apply-->OK
4.png -
测试。在web下的index.jsp里面随便输入点东西,然后启动项目,看到index.jsp里面有输入的东西就算做成功了!
4.2 导入jar包+配置+测试
- 导入jar。在WEB-INF下新建lib,把spring的jar拷贝进去,右击lib文件夹-->点击Add as Library
- 集成Spring。右击项目-->New-->Directory-->名字叫 resources-->OK。右击resources-->点击Mark Directory as-->Resources Root。
- 创建applicationContext.xml。右击resources-->点击New-->点击File-->命名 applicationContext.xml
- 拷贝配置到applicationContext.xml。xml的头从官方文档拷贝的。配置个bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--配置个bean,用于测试-->
<bean id="myDate" class="java.util.Date"></bean>
</beans>
- 创建测试文件夹。右击项目-->New-->Directory-->名字叫 test-->OK。test-->点击Mark Directory as-->Test Resources Root。
- 创建测试基类。右击test-->New-->Java Class-->输入 cn.wangningbo.ssm.BaseTest。代码如下
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class BaseTest {
}
- 创建SpringTest。SpringTest继承BaseTest
public class SpringTest extends BaseTest {
@Autowired
private Date myDate;
@Test
public void test() throws Exception {
System.out.println(myDate);
}
}
- 运行测试方法。打印出时间无误,成功!Spring集成完毕!
5.Spring+SpringMVC
- 导入jar
- 配置web.xml
- 字符编码过滤器
- applicationContext-mvc.xml
- 默认控制器
- 视图解析器
- 文件上传
5.1导入jar包
- 把springmvc的jar拷贝到lib中。在lib中选中刚才拷贝的jar包,右击选择Add as Library
5.2配置web.xml
方案1:独立容器方案,spring和springmvc都有自己的context
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--Spring容器初始化-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置springmvc-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!--项目已启动就加载-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--注意这里配置的 / 而不是 /* 。因为 /* 会拦截所有,包括jsp,而 / 也会拦截所有,但不包含jsp-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
注意:web.xml中的spring容器与springmvc的容器配置形成了‘子从上下文’,所谓子从上下文就是儿子可以拿父亲的,但是父亲不能拿儿子的!RootContext中是Service和Mapper/Repository,而WebAPPContext中是Controller,所以有个特点:Controller可以注入Service,而Service不能注入Controller
5.3配置applicationContext-mvc.xml
- 在src下创建对应的controller包。
- 在WEB-INF下创建views文件夹
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描controller-->
<context:component-scan base-package="cn.wangningbo.ssm.controller"/>
<!--静态资源处理-->
<mvc:default-servlet-handler/>
<!--识别@requestMapper等注解支持-->
<mvc:annotation-driven/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
- 在Controller包下创建一个DeptController类,用于测试
@Controller
@RequestMapping("/dept")
public class DeptController {
@RequestMapping("/index")
public String index() {
return "dept/index";
}
@RequestMapping("/json")
@ResponseBody
public String json() {
return "wangningbo";
}
}
- 在views下创建dept文件夹,在dept下创建index.jsp。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
dept index
</body>
</html>
- 测试!启动项目,浏览器地址栏输入 http://localhost/dept/index 和 http://localhost/dept/json 分别访问,拿到数据就代表成功!
- 在web.xml配置过滤器,处理post请求乱码问题
<!--配置过滤器处理post请求乱码,get请求在tomcat8那里已经解决-->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.Spring+MyBatis
jdbc.properties-->Datasource -->SqlSessionFactory-->扫描Repository-->事务管理器-开启注解事务
6.1 导入jar包
- 把MyBatis的jar包拷贝到lib
- 再把另外两个jar拷贝进去
- 继续把MyBatis集成Spring所需要的jar拷贝进去
- 在lib中选中刚才拷贝的jar包,右击选择Add as Library。
6.2 jdbc.properties
在resources创建jdbc.properties
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql:///mybatis_base
jdbc.username = root
jdbc.password = apy06942
6.3 配置applicationContext.xml
创建包domain、mapper、query、service
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--jdbc.properties + Datasource + SqlSessionFactory + 扫描Repository + 事务管理器-开启注解事务-->
<!--扫描service-->
<context:component-scan base-package="cn.wangningbo.ssm.service"/>
<!--加载数据库配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--maxActive: 最大连接数量 -->
<property name="maxActive" value="150"/>
<!--minIdle: 最小空闲连接 -->
<property name="minIdle" value="5"/>
<!--maxIdle: 最大空闲连接 -->
<property name="maxIdle" value="20"/>
<!--initialSize: 初始化连接 -->
<property name="initialSize" value="30"/>
<!-- 用来配置数据库断开后自动连接的 -->
<!-- 连接被泄露时是否打印 -->
<property name="logAbandoned" value="true"/>
<!--removeAbandoned: 是否自动回收超时连接 -->
<property name="removeAbandoned" value="true"/>
<!--removeAbandonedTimeout: 超时时间(以秒数为单位) -->
<property name="removeAbandonedTimeout" value="10"/>
<!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒 -->
<property name="maxWait" value="1000"/>
<!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. -->
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
<property name="numTestsPerEvictionRun" value="10"/>
<!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程 -->
<property name="minEvictableIdleTimeMillis" value="10000"/>
<property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
</bean>
<!--配置sqlSessionFactory-->
<!--SqlSessionFactoryBean这个类其实就是代替了那个MyBatis-Config.xml文件,那个MyBatis-Config.xml文件就是用来拿SqlSessionFactory的-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"/>
<!--别名包-->
<property name="typeAliasesPackage" value="cn.wangningbo.ssm.domain,cn.wangningbo.ssm.query"/>
<!--映射器-->
<property name="mapperLocations" value="classpath:cn/wangningbo/ssm/mapper/*Mapper.xml"/>
</bean>
<!--方案1:一个一个配置-->
<!--
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<property name="mapperInterface" value="cn.wangningbo.ssm.mapper.UserMapper"/>
</bean>
-->
<!--方案2:扫描Mapper,会扫描这个包里面所有Mapper接口,通过MapperFactoryBean创建所有的Mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--SqlSessionFactory会自动注入 所以这里注释掉了-->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory" />-->
<property name="basePackage" value="cn.wangningbo.ssm.mapper"></property>
</bean>
</beans>
- 在mapper包下创建DeptMapper接口
- 在resources下创建一个文件夹,名字为 cn/wangningbo/ssm/mapper,在mapper下创建创建一个DeptMapper.xml。(Dept和DeptMapper虽然不在同一个包下,但是DeptMapper.xml在资源文件夹下,而且它与Dept的前面路径一样,都是cn.wangningbo.ssm.mapper,所以最后会编译到一起)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--注意:这里的namespace是拷贝的DeptMapper接口的完全限定名-->
<mapper namespace="cn.wangningbo.ssm.mapper.DeptMapper">
<!--List<Dept> loadAll();-->
<select id="loadAll" resultType="Dept">
SELECT * from t_dept
</select>
<!--void save(Dept dept);-->
<insert id="save" parameterType="Dept">
INSERT into t_dept(name) values(#{name})
</insert>
</mapper>
- 在domain里创建Dept类
public class Dept {
private Long id;
private String name;
提供构造方法,提供get和set方法,提供toString
}
- 在mapper包里写接口
public interface DeptMapper {
List<Dept> loadAll();
void save(Dept dept);
}
- 在DeptMapper里写实现接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.wangningbo.ssm.domain.DeptMapper">
<!--List<Dept> loadAll();-->
<select id="loadAll" resultType="Dept">
SELECT * from t_dept
</select>
<!--void save(Dept dept);-->
<insert id="save" parameterType="Dept">
INSERT into t_dept(name) values(#{name})
</insert>
</mapper>
- 写Service接口
public interface IDeptService {
List<Dept> getAll();
void add(Dept dept);
}
- 在Service包下创建一个实现包 impl,在impl下创建一个接口的实现类
@Service
public class DeptServiceImpl implements IDeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> getAll() {
return deptMapper.loadAll();
}
@Override
public void add(Dept dept) {
deptMapper.save(dept);
}
}
- 测试!在IDeptService接口里右击鼠标Go To创建测试,测试类继承于BaseTest。测试那两个接口方法,测试loadALl方法无误,成功!
public class IDeptServiceTest extends BaseTest {
@Autowired
private IDeptService deptService;
@Test
public void getAll() {
List<Dept> depts = deptService.getAll();
depts.forEach(dept -> System.out.println(dept));
}
@Test
public void add() {
}
}
6.4配置事务
- 注解式事务:
- 1)配置事务管理:用jdbc事务管理器
- 2)开启注解事务
- 3)在service脑袋上面加@Transational
- 在applicationContext.xml尾部配置事务
<!--1)配置事务管理:用jdbc事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2)开启注解事务-->
<tx:annotation-driven/>
- 最终applicationContext.xml如下所示
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--jdbc.properties + Datasource + SqlSessionFactory + 扫描Repository + 事务管理器-开启注解事务-->
<!--扫描service-->
<context:component-scan base-package="cn.wangningbo.ssm.service"/>
<!--加载数据库配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--maxActive: 最大连接数量 -->
<property name="maxActive" value="150"/>
<!--minIdle: 最小空闲连接 -->
<property name="minIdle" value="5"/>
<!--maxIdle: 最大空闲连接 -->
<property name="maxIdle" value="20"/>
<!--initialSize: 初始化连接 -->
<property name="initialSize" value="30"/>
<!-- 用来配置数据库断开后自动连接的 -->
<!-- 连接被泄露时是否打印 -->
<property name="logAbandoned" value="true"/>
<!--removeAbandoned: 是否自动回收超时连接 -->
<property name="removeAbandoned" value="true"/>
<!--removeAbandonedTimeout: 超时时间(以秒数为单位) -->
<property name="removeAbandonedTimeout" value="10"/>
<!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒 -->
<property name="maxWait" value="1000"/>
<!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. -->
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
<property name="numTestsPerEvictionRun" value="10"/>
<!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程 -->
<property name="minEvictableIdleTimeMillis" value="10000"/>
<property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
</bean>
<!--配置sqlSessionFactory-->
<!--SqlSessionFactoryBean这个类其实就是代替了那个MyBatis-Config.xml文件,那个MyBatis-Config.xml文件就是用来拿SqlSessionFactory的-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"/>
<!--别名包-->
<property name="typeAliasesPackage" value="cn.wangningbo.ssm.domain,cn.wangningbo.ssm.query"/>
<!--映射器-->
<property name="mapperLocations" value="classpath:cn/wangningbo/ssm/mapper/*Mapper.xml"/>
</bean>
<!--方案1:一个一个配置-->
<!--
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<property name="mapperInterface" value="cn.wangningbo.ssm.mapper.UserMapper"/>
</bean>
-->
<!--方案2:扫描Mapper,会扫描这个包里面所有Mapper接口,通过MapperFactoryBean创建所有的Mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--SqlSessionFactory会自动注入 所以这里注释掉了-->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory" />-->
<property name="basePackage" value="cn.wangningbo.ssm.mapper"></property>
</bean>
<!--
注解式事务
1)配置事务管理:用jdbc事务管理器
2)开启注解事务
3)在service脑袋上面加@Transational
-->
<!--1)配置事务管理:用jdbc事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2)开启注解事务-->
<tx:annotation-driven/>
</beans>
- 在Service层的实现类那里开启事务
@Service
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class DeptServiceImpl implements IDeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> getAll() {
return deptMapper.loadAll();
}
@Transactional
@Override
public void add(Dept dept) {
deptMapper.save(dept);
//int i = 1 / 0; //用于测试事务
}
}
- 测试事务
public class IDeptServiceTest extends BaseTest {
@Autowired
private IDeptService deptService;
@Test
public void getAll() {
List<Dept> depts = deptService.getAll();
depts.forEach(dept -> System.out.println(dept));
}
@Test
public void add() {
//测试事务
deptService.add(new Dept("nb"));
}
}
- 在1/0存在时,事务进行报错回滚,在1/0不存在时,发现已经添加到数据库,成功了!
6.5集成到Controller的DeptController
@Controller
@RequestMapping("/dept")
public class DeptController {
@Autowired
private IDeptService deptService;
@RequestMapping("/index")
public String index() {
return "dept/index";
}
@RequestMapping("/json")
@ResponseBody
public List<Dept> json() {
return deptService.getAll();
}
}
6.6启动项目进行测试
启动项目,打开浏览器,地址栏输入 http://localhost/dept/json 访问,看到从数据库拿到的真实数据。成功!
网友评论