本篇主要講解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的配置文件集合了三層的配置,其實在真正
項目開發中,我們應該將三層的配置分來,這樣總體架構會更加清晰。