前言
自己是在CentOS7的IntelliJ IDEA里开发的,里面中文输入法有问题经常用不了,所以这里用了很多chinglish,希望不要介意;
一:pom依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>me.silentdoer</groupId> <artifactId>combine-spring-struts2-mybatis</artifactId> <version>1.0-SNAPSHOT</version> <properties> <spring.group>org.springframework</spring.group> <spring.version>4.3.4.RELEASE</spring.version> <logback.group>ch.qos.logback</logback.group> <logback.version>1.2.3</logback.version> <slf4j.group>org.slf4j</slf4j.group> <slf4j.version>1.7.25</slf4j.version> <mybatis.group>org.mybatis</mybatis.group> <mybatis.version>3.4.4</mybatis.version> <mybatis-spring.version>1.3.1</mybatis-spring.version> <mysql.group>mysql</mysql.group> <mysql-connector.version>5.1.41</mysql-connector.version> <alibaba.group>com.alibaba</alibaba.group> <druid.version>1.1.6</druid.version> <fastjson.version>1.2.41</fastjson.version> <dom4j.group>dom4j</dom4j.group> <dom4j.version>1.6.1</dom4j.version> <junit.group>junit</junit.group> <junit.version>4.12</junit.version> </properties> <dependencies> <!-- spring --> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> <!-- scope 默认是compile的 --> <scope>compile</scope> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <!-- struts2 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.20</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-convention-plugin</artifactId> <version>2.3.20</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>2.3.20</version> </dependency> <!-- database begin --> <dependency> <groupId>${mybatis.group}</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>${mybatis.group}</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring.version}</version> </dependency> <dependency> <groupId>${mysql.group}</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector.version}</version> </dependency> <dependency> <groupId>${alibaba.group}</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- database end --> <!-- tool begin --> <dependency> <groupId>${alibaba.group}</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>${dom4j.group}</groupId> <artifactId>dom4j</artifactId> <version>${dom4j.version}</version> </dependency> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.9</version> </dependency> <!-- log begin --> <dependency> <groupId>${slf4j.group}</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>${logback.group}</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>${logback.group}</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- log end --> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <!-- 用于测试 begin --> <dependency> <groupId>${spring.group}</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>${junit.group}</groupId> <artifactId>junit</artifactId> <!-- version据说还可以是一个范围值 --> <version>${junit.version}</version> <!-- 表示这个jar包是用于测试,打包时不会将此jar包打包进去 --> <scope>test</scope> </dependency> <!-- 用于测试 end --> <!-- 依赖jar包依赖的组件 begin--> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> <!-- compile 表示编译时和运行时都需要(但IDE可能有bug,不行的话还是自己主动将jar包放到lib目录 --> <scope>compile</scope> </dependency> <!-- mq and cache --> <!--<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>4.1.0</version> </dependency>--> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
二:配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--spring--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- other filters --> <!--struts2, use with last filter--> <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>
三:配置struts2/mybatis/spring/mapper配置文件
注:均放在resources目录里
1.struts.xml
(struts1和2都可以用这个名字,struts2会自动加载就像logback.xml一样)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <!-- use development mode, when exception occur will show in the response body --> <constant name="struts.devMode" value="true" /> <!-- ke yi bu yao --> <!--<constant name="struts.objectFactory" value="spring" />--> <constant name="struts.i18n.encoding" value="utf-8" /> <!-- use to separate diff func action, extends is important for link struts2-spring --> <!-- namespace like RequestMapping on controller --> <!-- if namespace is /, then http://localhost:8090/getStudent?uid=1, if namespace is /entity, ..8090/entity/getStudent?uid=1 --> <package name="entity-resolver" extends="struts-default" namespace="/entity"> <!-- name is in Struts registry key&context/student, class is the action class or spring beanName --> <!-- method attr is for special method to be handlerMethod --> <action name="getStudent" class="studentAction"> <result name="success">/WEB-INF/content/vo/student.jsp</result> <result name="error">/WEB-INF/content/common/error.jsp</result> </action> </package> <package name="index" extends="struts-default" namespace="/"> <!-- Struts2 process url also bu xu yao suffix --> <action name="index" class="indexAction"> <result name="success">/index.html</result> </action> </package> <!--<package name="about-permission" extends="struts-default"></package>--> </struts>
2.mybatis-config.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> <typeAlias type="me.silentdoer.ssmdemo.pojo.Student" alias="User"/> </typeAliases> <!--<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/db_test"/> <property name="username" value="test"/> <property name="password" value="test"/> </dataSource> </environment> </environments>--> <mappers> <!-- must absolute path --> <mapper resource="config/mybatis/mapper/StudentMapper.xml"/> </mappers> </configuration>
3.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--<tx:annotation-driven transaction-manager="txManager" />--> <!--配置事务管理器--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- transaction --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="select*" read-only="true"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- first * is all visit qualifier --> <!-- aop --> <aop:config> <aop:pointcut id="pointcut" expression="execution(* me.silentdoer.ssmdemo.dao.impl.StudentDaoImpl.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/> </aop:config> <!-- datasource, can be replace with Druid --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/db_test"/> <property name="username" value="test"/> <property name="password" value="test"/> </bean> <!-- 配置sessionFacfory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 加载dataSource --> <property name="dataSource" ref="dataSource"/> <!--加载usermapper.xml--> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <context:component-scan base-package="me.silentdoer.ssmdemo"> <!-- exclude by regex, also can use aspectj ex to exclude --> <context:exclude-filter type="regex" expression="me.silentdoer.ssmdemo.pojo..*"/> </context:component-scan> <!-- userDao, it's extends SqlSessionDapSupport --> <!--<bean id="studentDao" class="me.silentdoer.ssmdemo.dao.impl.StudentDaoImpl"> <!– in setSqlsessionFactory method: this.sqlSession = new SqlSessionTemplate(sqlSessionFactory) –> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>--> <!--userService--> <!--<bean id="studentService" class="me.silentdoer.ssmdemo.service.impl.StudentServiceImpl"> <property name="studentDao" ref="studentDao"/> </bean>--> <!--userAction--> <!--<bean id="userAction" class="me.silentdoer.ssmdemo.action.student.StudentAction"> <property name="studentService" ref="studentService"/> </bean>--> </beans>
4.StudentMapper.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="me.silentdoer.ssmdemo.pojo.StudentMapper"> <resultMap id="studentResultMap" type="me.silentdoer.ssmdemo.pojo.Student"> <id property="uid" column="uid"/> <result property="name" column="name"/> <result property="gender" column="gender"/> <result property="createTime" column="create_time"/> <result property="updateTime" column="update_time"/> </resultMap> <!--<insert id="insertOne"> insert into student(name values (#{name}) </insert>--> <select id="selectOne" resultMap="studentResultMap"> select uid, name, gender, create_time, update_time from student where uid=#{uid} </select> </mapper>
四:代码实现
1.pojo层的编码
package me.silentdoer.ssmdemo.pojo; import java.io.Serializable; import java.sql.Timestamp; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 2:11 PM */ public class Student implements Serializable { private long uid; private String name; private int gender; private Timestamp createTime; // Timestamp is implements java.util.Date private Timestamp updateTime; public long getUid() { return uid; } public void setUid(long uid) { this.uid = uid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getGender() { return gender; } public void setGender(int gender) { this.gender = gender; } public Timestamp getCreateTime() { return createTime; } public void setCreateTime(Timestamp createTime) { this.createTime = createTime; } public Timestamp getUpdateTime() { return updateTime; } public void setUpdateTime(Timestamp updateTime) { this.updateTime = updateTime; } @Override public String toString(){ return String.format("[uid=%s, name=%s, gender=%s, createTime=%s, updateTime=%s]", this.uid, this.name, this.gender, this.createTime, this.updateTime); } }
2.dao层的编码
package me.silentdoer.ssmdemo.dao; import me.silentdoer.ssmdemo.pojo.Student; import org.apache.ibatis.annotations.Param; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 1:40 PM */ public interface StudentDao { Student selectOne(@Param("uid") long uid); }
package me.silentdoer.ssmdemo.dao.impl; import me.silentdoer.ssmdemo.dao.StudentDao; import me.silentdoer.ssmdemo.pojo.Student; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.support.SqlSessionDaoSupport; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import javax.annotation.Resource; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 2:31 PM */ // this.sqlSessionProxy.selectOne(statement), proxy will use invoke method to call sqlSessionFactory.openSession(); // this session is sqlSession = new SqlSessionTemplate(sqlSessionFactory); not real SqlSession, in template use proxy to exec @Repository("studentDao") // default singleton, but in the inside it's will use SqlSessionFactory to openSession(), so can be singleton. public class StudentDaoImpl extends SqlSessionDaoSupport implements StudentDao { public Student selectOne(long uid) { final SqlSession session = this.getSqlSession(); String statement = "me.silentdoer.ssmdemo.pojo.StudentMapper.selectOne"; return session.selectOne(statement, uid); } /*@Autowired // by type @Qualifier("sqlSessionFactory")*/ @Resource // by name and default is setter rm set and lower first char @Override public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { super.setSqlSessionFactory(sqlSessionFactory); } }
3.service层的编码
package me.silentdoer.ssmdemo.service; import me.silentdoer.ssmdemo.pojo.Student; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 2:43 PM */ public interface StudentService { // ERP Logic layer, like login process etc. Student getOneUserWithLogic(Long uid); }
package me.silentdoer.ssmdemo.service.impl; import me.silentdoer.ssmdemo.dao.StudentDao; import me.silentdoer.ssmdemo.pojo.Student; import me.silentdoer.ssmdemo.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 2:43 PM */ @Service("studentService") // need trans to studentService, otherwise will be studentServiceImpl will occur can not get bean by name public class StudentServiceImpl implements StudentService { // field name can diff with it's getter&setter; in structure is use getter&setter name. private StudentDao studentDao; @Autowired @Qualifier("studentDao") public void setStudentDao(StudentDao studentDao) { this.studentDao = studentDao; } public Student getOneUserWithLogic(Long uid) { // some logic impl if(uid == null){ throw new IllegalArgumentException("uid is not null, please check."); } System.out.println(String.format("uid is:%s", uid)); Student student = this.studentDao.selectOne(uid); return student; } }
4.action层的编码(controller)
package me.silentdoer.ssmdemo.action.index; import com.opensymphony.xwork2.ActionSupport; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 10:53 PM */ @Controller public class IndexAction extends ActionSupport { }
package me.silentdoer.ssmdemo.action.student; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import me.silentdoer.ssmdemo.pojo.Student; import me.silentdoer.ssmdemo.service.StudentService; import org.apache.struts2.interceptor.RequestAware; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import javax.annotation.Resource; import java.util.Map; /** * @author silentdoer * @version 1.0 * @description the description * @date 4/21/18 2:45 PM */ @Scope("prototype") // must be set prototype @Controller("studentAction") // Or @Component for component-scan by annotation-filter public class StudentAction extends ActionSupport /*implements RequestAware*/ { private static final long serialVersionUID = 1L; // ActionSupport implements Serializable private Long uid; private Student student; @Resource private StudentService studentService; // like SpringMVC InternalResourceViewResolver to search success mapping file @Override public String execute(){ // setter for jsp usage, struts2 will purge the map to request attr when after execute(). Map request = (Map) ActionContext.getContext().get("request"); // request obj is generate&store by struts2, so request.put is also struts2 to put key-value to request attr. request.put("requestAttrKey", "value8888888"); try { Student student = this.studentService.getOneUserWithLogic(this.uid); System.out.println(String.format("The student is: %s", student)); this.student = student; }catch (Exception ex){ // to log exception ex.printStackTrace(); request.put("error", ex.getMessage()); return ERROR; // error page } return SUCCESS; // normal page } public void setStudentService(StudentService studentService) { this.studentService = studentService; } public void setUid(Long uid) { this.uid = uid; } // student will put to request attr, key is student public Student getStudent() { return student; } }
五:数据库和表的建立
数据库名为db_test,表名为student,里面就五个字段,可以参考pojo建立;
六:源码地址
github地址:https://github.com/Silentdoer/demos.git的Combine-Spring-Struts2-Mybatis项目