本篇主要讲解Struts2与Spring+Mybatis的整合。
通过整合,由Spring管理Mybatis的mapper以及Struts2的Action。
项目分为mapper(dao从层)、service层、Action层。
使用工具及框架版本:
eclipse neon
Struts2.3
Spring3.2
Mybatis3.2.7
Tomcat7.0
MySql5.6
jdk1.7
项目结构如下图所示:
项目源码下载:点击下载
项目war包下载:点击下载
在线演示:点击观看
在本项目中,主要通过一个用户登录的实例来进行讲解。
数据库字段如下:
id-int
username-varchar(50)
password-varchar(50)
Mybatis与Spring的结合
可参考之前讲解过的一篇关于Mybatis与Spring整合的文章:点击打开链接
一、Spring+Mybatis
1、编写PO类
package com.sw.po;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:用户表po对象
*id:编号
*username:用户名
*password:密码
*/
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、编写SqlMapConfig.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.sw.po"/>
</typeAliases>
</configuration>
3、编写mapper接口
package com.sw.mapper;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:
*/
public interface UserMapper {
/*用户登录:根据用户名查找用户密码,检查是否匹配进行登录*/
public String findPassByName(String username)throws Exception;
}
4、编写mapper.xml文件
<?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="com.sw.mapper.UserMapper">
<!-- 用户登录(根据用户名查找返回密码,校验) -->
<select id="findPassByName" parameterType="String" resultType="String">
select password from user where username=#{username}
</select>
</mapper>
5、编写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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!-- 配置注解自动扫描范围 -->
<context:component-scan base-package="com.bs"></context:component-scan>
<!-- 事务管理器
对mybatis操作数据库事务控制,spring使用jdbc的事务控制类
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源
dataSource在applicationContext-dao.xml中配置了
-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 管理mybatis -->
<!-- mapper配置 -->
<!-- 让spring管理sqlsessionfactory 使用mybatis-spring.jar -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
<!-- mapper扫描(自动扫描) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描的包名 -->
<property name="basePackage" value="com.sw.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
</beans>
6、db.properties配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1/xc?character=utf-8
jdbc.username=root
jdbc.password=****
7、到了这里,Mybatis与Spring的整合已经完成,接下来我们测试一下。
package com.sw.test;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sw.mapper.UserMapper;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:Spring与Mybatis整合测试
*/
public class UserDaoTest {
private ApplicationContext applicationContext;
@Before
public void setUp() throws Exception {
//spring
applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void test() throws Exception {
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
String pass=userMapper.findPassByName("bs");
System.out.println(pass);
}
}
结果如下:
现在Spring与Mybatis的整合已经成功,接下来编写Service层代码。
二、service层编写
1、Service层接口编写
package com.sw.service;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:Service层接口
*/
public interface UserService {
public final static String SERVICE_NAME="UserServiceImpl";
/*用户登录验证*/
public String findLoginCheck(String username)throws Exception;
}
2、applicationContext.xml编写:在上面代码的基础上加入如下代码:
<!-- Service层 -->
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- aop -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.sw.service.impl.*.*(..))"/>
</aop:config>
<!-- 方法实现配置 -->
<bean id="UserServiceImpl" class="com.sw.service.impl.UserServiceImpl"></bean>
3、实现service层接口
package com.sw.service.impl;
import com.bs.container.ServiceProvider;
import com.sw.mapper.UserMapper;
import com.sw.service.UserService;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:Service层接口实现类
*/
public class UserServiceImpl implements UserService{
@Override
public String findLoginCheck(String username) throws Exception {
UserMapper userMapper=(UserMapper) ServiceProvider.getService("userMapper");
String pass = userMapper.findPassByName(username);
return pass;
}
}
4、编写工具类,此工具类主要用于加载applicationContext.xml文件,以避免每次加载浪费资源
package com.bs.container;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:服务类,用用户加载applicationContext.xml文件
*/
public class ServiceProvideCord {
protected static ApplicationContext applicationContext;
public static void load(String fileName){
applicationContext = new ClassPathXmlApplicationContext(fileName);
}
}
package com.bs.container;
import org.apache.commons.lang.StringUtils;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:服务类
*/
@SuppressWarnings("static-access")
public class ServiceProvider {
private static ServiceProvideCord serviceProvideCord;
//静态加载
static{
serviceProvideCord = new ServiceProvideCord();
serviceProvideCord.load("classpath:applicationContext.xml");
}
public static Object getService(String serviceName){
//服务名称为空
if(StringUtils.isBlank(serviceName)){
throw new RuntimeException("当前服务名称不存在");
}
Object object = null;
if(serviceProvideCord.applicationContext.containsBean(serviceName)){
//获取到
object = serviceProvideCord.applicationContext.getBean(serviceName);
}
if(object==null){
throw new RuntimeException("当前服务名称【"+serviceName+"】下的服务节点不存在");
}
return object;
}
}
5、接下来,我们可以对service层进行测试了,代码如下:
package com.sw.test;
import org.junit.Test;
import com.bs.container.ServiceProvider;
import com.sw.service.UserService;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:Service层测试
*/
public class UserServiceTest {
@Test
public void test() throws Exception {
UserService userService=(UserService) ServiceProvider.getService(UserService.SERVICE_NAME);
String pass=userService.findLoginCheck("bs");
System.out.println(pass);
}
}
结果如下图所示:
如上所示,Service层的编写已经完成,并且不存在错误,接下来我们加入Struts2进行整合
三、Struts2整合
加入Struts,主要由Spring管理其Action,并且Struts2可以使用Spring的注解进行开发。
1、编写VO对象,VO对象用于映射表单内提交的数据。
package com.sw.view.form;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:持久层bean-对应于数据库表(user)--即表单提交的数据
*/
public class UserForm {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、编写baseAction文件,该文件主要用于封装Request于Response
package com.sw.view.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import com.opensymphony.xwork2.ActionSupport;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:封装Request与Response
*/
public class BaseAction extends ActionSupport implements ServletRequestAware,ServletResponseAware{
private static final long serialVersionUID = 1L;
protected HttpServletRequest request;
protected HttpServletResponse response;
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
}
3、编写Action文件,该文件主要用于处理登录动作
package com.sw.view.action;
import com.bs.container.ServiceProvider;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.sw.service.UserService;
import com.sw.view.form.UserForm;
/*
*@Author swxctx
*@time 2017年5月11日
*@Explain:登录Action
*/
public class LoginAction extends BaseAction implements ModelDriven<UserForm>{
private static final long serialVersionUID = 1L;
/*创建vo对象*/
UserForm userForm = new UserForm();
/*加载applicationContext.xml*/
private UserService userService = (UserService)ServiceProvider.getService(UserService.SERVICE_NAME);
@Override
public UserForm getModel() {
// TODO Auto-generated method stub
return userForm;
}
/*处理*/
@Override
public String execute() throws Exception {
/*调用service层LoginCheck函数校验*/
String pass = userService.findLoginCheck(userForm.getUsername());
if(userForm.getPassword().equals(pass)){
return "success";
}else{
return "error";
}
}
}
4、编写相关applicationContext.xml文件,该文件主要用于将Action放入Spring管理
在之前的.xml文件中加入如下代码即可。
<!-- 管理struts2 action-->
<!-- 登录action -->
<bean id="loginAction" class="com.sw.view.action.LoginAction" scope="prototype"></bean>
5、编写struts2.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory" value="spring"></constant>
<!-- struts的action配置文件 -->
<!-- 所有的action都应该放在对应的package下 -->
<package name="ssm-template" extends="struts-default">
<!-- 用户登录 -->
<action name="login" class="loginAction">
<!-- 定义逻辑视图和物理资源之间的映射 -->
<result name="success" >
<param name="location">/success.html</param>
</result>
<result name="error">/err.html</result>
</action>
</package>
</struts>
6、编写web.xml文件,用于处理监听器等操作
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ssm-template</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
7、编写相关的html文件
login.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login.action" mephod="post">
用户:<input type="text" id="username" name="username" placeholder="用户名"><br>
密码:<input type="password" id="password" name="password" placeholder="密码" ><br>
<input type="submit" value="提交">
</form>
</body>
</html>
success.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<p>登录成功</p>
</body>
</html>
err.html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>err</title>
</head>
<body>
<p>登录失败</p>
</body>
</html>
至此,Struts2与Spring以及Mybatis的整合已经全部结束了,接下来启动tomcat进行测试,如下图所示:
登录页面:
成功页面:
失败页面:
如上测试可看出,此项目可以运行了,也就是说在整合过程中没有差错。
总结:在此项目中,将ssm2进行整合,个人觉得对比ssh2好的一点就是思路比较清晰,不用很多dao接口
那么乱,但是在此项目中,还是有一点缺陷,那就是spring的配置文件集合了三层的配置,其实在真正
项目开发中,我们应该将三层的配置分来,这样总体架构会更加清晰。