[java web]Idea+maven+spring4+hibernate5+struts2整合过程
摘要
最近也在网上找了些教程,试着使用maven进行包依赖关系的管理,也尝试着通过注解的方式来整合ssh框架。在这个过程中,踩了不少的坑。折腾很长时间,才算把架子折腾起来。这里把结果整理下,作为以后工作中的参考。
项目结构
关于maven如何使用,可自行搜索,默认你有一定的maven基础。maven建议中央仓库配置成阿里云的,可以下载速度快一些。地址

1、开始之前,需要通过maven进行ssh jar包引入。可以参考下面的pom.xml
<?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>com.demo</groupId> <artifactId>mavenapp</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>mavenapp Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <!--源码编码--> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <!-- spring版本号 --> <spring.version>4.3.8.RELEASE</spring.version> <!-- hibernate版本号 --> <hibernate.version>5.1.7.Final</hibernate.version> <!-- struts2版本号 --> <struts2.version>2.5.10</struts2.version> </properties> <dependencies> <!--JUnit4依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- Spring 核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring web依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring整合ORM框架依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <!-- Struts2 核心依赖 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>${struts2.version}</version> </dependency> <!-- Struts2和Spring整合依赖 --> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-spring-plugin</artifactId> <version>${struts2.version}</version> </dependency> <!-- Hibernate 核心依赖 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <!-- MySQL 依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.42</version> </dependency> <!-- C3P0 依赖 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5</version> </dependency> <!-- AspectJ依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <!-- SLF4J依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> </dependencies> <build> <finalName>mavenapp</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
2、将resources设置为资源目录,并添加如上图所示的jdbc属性文件,struts2配置文件,日志属性文件,spring配置文件
内容分别如下:
<?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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.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"> <!-- 打开spring的annotation的支持 --> <context:annotation-config/> <!--引入jdbc属性配置文件--> <context:property-placeholder location="classpath:jdbc.properties"/> <!--对me.demo下所有类文件进行扫描--> <context:component-scan base-package="me.demo.*"/> <!--c3p0连接池配置--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--sessionFactory配置 可以省略hibernate.cfg.xml配置文件--> <!--使用jpa注解形式的pojo对象,而去掉*.hbm.xml的Hibernate映射文件--> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!--配置数据源--> <property name="dataSource" ref="dataSource"/> <!-- 设置spring去哪个包中查找相应的实体类 --> <property name="packagesToScan"> <list> <value>me.demo.domain</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <!--是否自动创建表结构--> <prop key="hibernate.hbm2ddl.auto">update</prop> <!--方言--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <!--hibernate中事务是需要在dao执行sql相关语句时来手动开启的, 然后底层实现代码时由getCurrentSession得到的session中可以得到transaction,所以可以正常运行. 这里,需要因为我们把sessionFactory的产生放在spring配置文件中,即让服务器启动时就创建这个对象,这样的话它就被存在一个上下文环境中,即在SpringSessionContext中保存 所以我们要把绑定当前线程session改成绑定这个spring上下文环境,即设置为由spring环境管理(因为事务aop也是在spring中),这时spring中的事务配置才会起作用(当然,以前是thread上下文环境的session, 而事务托管在spring上下文中,当然spring无法管理到thread上下文的session的事务)。--> <prop key="hibernate.current_session_context_class"> org.springframework.orm.hibernate5.SpringSessionContext </prop> </props> </property> <!--自动扫描注解方式的hibernate类文件--> </bean> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 基于注解的事务,当注解中发现@Transactional时,使用id为“transactionManager”的事务管理器 --> <!-- 如果没有设置transaction-manager的值,则spring以缺省默认的事务管理器来处理事务, 默认事务管理器为第一个加载的事务管理器 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!--配置事务的传播性--> <!--<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">--> <!--<tx:attributes>--> <!--<tx:method name="find*" read-only="true" />--> <!--<tx:method name="get*" read-only="true" />--> <!--<tx:method name="login*" read-only="true" />--> <!--<tx:method name="add*" propagation="REQUIRED" />--> <!--<tx:method name="update*" propagation="REQUIRED" />--> <!--<tx:method name="delete*" propagation="REQUIRED" />--> <!--<tx:method name="save*" propagation="REQUIRED" />--> <!--<tx:method name="test*" propagation="REQUIRED" />--> <!--<tx:method name="*Transaction" propagation="REQUIRED" />--> <!--<tx:method name="*" propagation="REQUIRED" />--> <!--</tx:attributes>--> <!--</tx:advice>--> <!--<!–配置哪些类的哪些方法参与事务 因为业务处理发生在service层,这里配置在service中的类–>--> <!--<aop:config proxy-target-class="true">--> <!--<aop:pointcut id="all-method" expression="execution(public * me.demo.service.*.*(..))"></aop:pointcut>--> <!--<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="all-method"/>--> <!--</aop:config>--> </beans>
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/sshdemo jdbc.username=root jdbc.password=abcd
log4j.rootCategory=INFO, console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %t %c{2}:%L - %m%n
<?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.objectFactory" value="spring"/> <constant name="struts.i18n.encoding" value="utf-8"/> <!--默认action配置--> <package namespace="/" name="default" extends="struts-default"> <default-action-ref name="default"/> <action name="default"> <result>/index.jsp</result> </action> </package> <!--通过通配符的方式配置action--> <package name="user" namespace="/" extends="struts-default"> <action name="user_*" method="{1}" class="userAction"> <result name="success">/index.jsp</result> <allowed-methods> register </allowed-methods> </action> </package> </struts>
3、三层结构,以及注解的使用
package me.demo.action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import me.demo.domain.User; import me.demo.service.UserService; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; @Controller("userAction") @Scope("prototype") //默认是单例模式,需配置多例 public class UserAction extends ActionSupport implements ModelDriven<User> { private static final Logger log = LogManager.getLogger (UserAction.class); private User user = new User (); @Autowired private UserService userService; @Override public User getModel() { return user; } public String login() { String login = userService.login (user); return login; } public String register() { System.out.println (user); log.info (user); String register = userService.register (user); return register; } }
package me.demo.dao.Impl; import me.demo.dao.UserDao; import me.demo.domain.User; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import org.springframework.stereotype.Repository; import java.util.List; @Repository() @Scope("prototype") public class UserDaoImpl extends HibernateDaoSupport implements UserDao { @Autowired public void setSessionFactoryOverride(SessionFactory sessionFactory) { super.setSessionFactory (sessionFactory); } @Override public void save(User user) { if (this.getHibernateTemplate () == null) System.out.println ("getHibernateTemplate == null"); this.getHibernateTemplate ().save (user); } @Override public User find(String username, String password) { List<User> users = (List<User>) this.getHibernateTemplate ().find ("from User where username=? and password=?", username, password); if (users.size () > 0) return users.get (0); return null; } }
package me.demo.dao; import me.demo.domain.User; /** * 接口 */ public interface UserDao { void save(User user); User find(String username, String password); }
package me.demo.domain; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; @Entity @Table(name = "t_users") public class User implements Serializable { @Id @GeneratedValue(generator = "autoGenerator")//根据数据库的主键生成策略 @GenericGenerator(name = "autoGenerator", strategy = "native") private Integer id; @Column private String name; @Column private String password; @Column private Integer sex; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", sex=" + sex + '}'; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package me.demo.service.Impl; import me.demo.dao.UserDao; import me.demo.domain.User; import me.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service() @Scope("prototype") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; public String login(User user) { User user1 = userDao.find (user.getName (), user.getPassword ()); if (user1 != null) return "success"; return "not found"; } public String register(User user) { userDao.save (user); return "success"; } }
package me.demo.service; import me.demo.domain.User; public interface UserService { String login(User user); String register(User user); }
4、web
<%-- Created by IntelliJ IDEA. User: Date: 2018/6/8 Time: 17:05 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>首页</title> </head> <body> url:${pageContext.request.contextPath} <a href="${pageContext.request.contextPath}/login.jsp">登录</a> <a href="${pageContext.request.contextPath}/register.jsp">注册</a><br> </body> </html>
<%-- Created by IntelliJ IDEA. User: Date: 2018/6/8 Time: 17:06 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录</title> </head> <body> <form action="${pageContext.request.contextPath}/login" method="post"> 姓名: <input name="name" type="text"> <br> <input type="submit" value="登录"> </form> </body> </html>
<%-- Created by IntelliJ IDEA. User: Date: 2018/6/8 Time: 17:07 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>注册</title> </head> <body> <form action="${pageContext.request.contextPath}/user_register.action" method="post"> 姓名: <input name="name" type="text"> <br> 密码:<input name="password" value="1234" type="password"> 性别: <input name="sex" type="radio" value="1">男 <input name="sex" type="radio" value="0">女 <input type="submit" value="注册"> </form> </body> </html>
5、配置tomcat服务器,然后启动即可,会自动生成数据库表结构(前提自己手动创建好数据库)
6、测试

总结
1、虽然网络上这样的文章很多,但自己动手实现,发现还是有很多错误,发现最多的是,由jar的版本问题引起的,比如在配置问价中org.springframework.orm.hibernate5.LocalSessionFactoryBean这个类所在的包,在hibernate3,4,5中都有,如果你在配置文件中所写的,和HibernateDaoSupport所使用的包版本不一致,就会出错。
2、<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>,方言的配置,hibernate关于mysql的方言就有三个,这里采用MySQL5Dialect。
3、然后就是事务了,采用事务的注解,需要在配置文件中进行配置事务管理器。
annotation-driven:
这是xsd中 对事务管理器的描述。
Indicates that transaction configuration is defined by Java 5 annotations on bean classes, and that proxies are automatically to be created for the relevant annotated beans. The default annotations supported are Spring's @Transactional and EJB3's @TransactionAttribute (if available). Transaction semantics such as propagation settings, the isolation level, the rollback rules, etc are all defined in the annotation metadata. See org.springframework.transaction.annotation.EnableTransactionManagement Javadoc for information on code-based alternatives to this XML element. ]]></xsd:documentation> </xsd:annotation> <xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> <xsd:annotation> <xsd:documentation source="java:org.springframework.transaction.PlatformTransactionManager"><
浙公网安备 33010602011771号