一、前期准备工作
1.项目介绍:
本文记述了搭建一个基于spring、struts2,Hibernate框架项目的完整过程。
使用Maven来管理项目。采用Junit进行单元测试。服务器使用Tomcat。
项目名为SS2HDemo,实现一个简单的登陆功能。
(1)登陆界面:
(2)登陆成功界面:
2.项目环境和工具
3.创建一个Web项目工程
二、SS2H开发过程
1.基础数据
(1)在mysql中创建数据库:ss2hdemo
(2)创建表:user,sql脚本如下
1 2 3 4 5 6 7 |
drop table if exists users; create table users( id int(10) not null auto_increment, name varchar(45) not null, password varchar(20) not null, primary key(id) )engine=InnoDB; |
2.配置Maven
配置pom.xml文件。配置用到的第三方依赖包。
注意:这个配置文件是根据项目实际需要不断修改的。这里提供的是最终配置文件。
另外,Intellij也会根据用到编写代码时用到的jar包自动识别提示修改pom.xml的功能(但不能完全依靠IDE的提示)。
这里HIbernate用到的版本是Hibernate3.*。而最新的是Hibernate4.*,两者之间存在一些用法区别,请注意。
【pom.xml】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.7player.ss2h</groupId> <artifactId>SS2HDemo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>SS2HDemo Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!--struts2--> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.20</version> </dependency> <!--使用Hibernate3--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.6.10.Final</version> </dependency> <!--spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>3.1.1.RELEASE</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> </dependencies> <build> <finalName>SS2HDemo</finalName> </build> </project> |
3.Hibernate相关
(1)对应数据库的user表,建立相应的User类(POJO),为MVC的模型层(Model)。放在cn.no7player.ssh.po包目录下:
【User.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package cn.no7player.ssh.po; /** * Created by zl on 1/21/2015. */ public class User { private int id; private String name; private String password; public int getId(){ return id; } public void setId(int id){ this.id = id; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public String getPassword(){ return password; } public void setPassword(String password){ this.password = password; } } |
(2)创建user对应的的hibernate配置文件——user.hbm.xml。文件放在项目的resources目录下:
【user.hbm.xml】
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.no7player.ssh.po"> <class name="User" > <id name="id" > <generator class="identity"/> </id> <property name="name"></property> <property name="password"></property> </class> </hibernate-mapping> |
(3)建立UserDAO接口,放在cn.no7player.ssh.dao包目录下
【UserDAO.java】
1 2 3 4 5 6 7 8 9 10 11 |
package cn.no7player.ssh.dao; import cn.no7player.ssh.po.User; import java.util.List; /** * Created by zl on 1/21/2015. */ public interface UserDao { public String addUser(User user); public List<User> findUserByName(String name); public List<User> listAll(); } |
(4)创建接口的实现:UserDAOImpl类
【UserDAOImpl.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package cn.no7player.ssh.dao.impl; import cn.no7player.ssh.dao.UserDao; import cn.no7player.ssh.po.User; import org.springframework.dao.DataAccessException; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import java.util.List; /** * Created by zl on 1/21/2015. */ @SuppressWarnings("ALL") public class UserDaoImpl extends HibernateDaoSupport implements UserDao{ @Override public String addUser(User user) { String success = ""; String name = user.getName(); if(findUserByName(name).size() == 0){ try { getHibernateTemplate().save(user); success = "User saved ok!"; } catch (DataAccessException e) { success = "Sorry, user can't be added."; } } else { success = "The username has been existed!"; } return success; } @SuppressWarnings("unchecked") @Override public List<User> findUserByName(String name) { return getHibernateTemplate().find("from User where name = ?",name); } @SuppressWarnings("unchecked") @Override public List<User> listAll() { return getHibernateTemplate().find(" from User "); } } |
4.Service业务逻辑层
建立Service层的接口以及其实现。该层用来处理业务逻辑。本例中功能较为简单,实现中只是简单调用dao层的接口。
(1)UserService接口,放在cn.no7player.ssh.service包目录下:
【UserService.java】
1 2 3 4 5 6 7 8 9 10 11 |
package cn.no7player.ssh.service; import cn.no7player.ssh.po.User; import java.util.List; /** * Created by zl on 1/21/2015. */ public interface UserService { public String addUser(User user); public List<User> findUserByName(String name); public List<User> listAll(); } |
(2)UserServiceImpl实现,放在cn.no7player.ssh.service.impl包目录下:
【UserServiceImpl.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package cn.no7player.ssh.service.impl; import cn.no7player.ssh.dao.UserDao; import cn.no7player.ssh.po.User; import cn.no7player.ssh.service.UserService; import java.util.List; /** * Created by zl on 1/21/2015. */ public class UserServiceImpl implements UserService{ private UserDao userDao; public UserDao getUserDao() { return userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public String addUser(User user) { return userDao.addUser(user); } @Override public List<User> findUserByName(String name) { return userDao.findUserByName(name); } @Override public List<User> listAll() { return userDao.listAll(); } } |
5.spring相关
(1)创建Spring的配置文件applicationContext.xml,放在resources目录下。
其中包含数据库的配置内容,根据个人环境修改。配置中还包含多个bean的例如注入的配置,可以根据自己的项目结构修改。
注意:部分内容可能会提示出错,原因是依赖的包没加入,要在pom.xml中加入对应的依赖包。比如如下hibernate3的依赖:
1 2 3 4 5 6 |
<!--使用Hibernate3--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.6.10.Final</version> </dependency> |
完整的applicationContext.xml:
【applicationContext.xml】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<?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 id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3307/ss2hdemo</value> </property> <property name="username" value="root"/> <property name="password" value="123456" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="mappingLocations"> <value>user.hbm.xml</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="transactionAttributes"> <props> <prop key="add">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean id="userDAO" class="cn.no7player.ssh.dao.impl.UserDaoImpl"> <property name="hibernateTemplate"> <ref bean="hibernateTemplate"/> </property> </bean> <bean id="userService" class="cn.no7player.ssh.service.impl.UserServiceImpl"> <property name="userDao"> <ref bean="userDAO"/> </property> </bean> </beans> |
(2)建立一个辅助工具类,用来获取ApplicationContext,放在cn.no7player.ssh.util包目录下:
【InitApplicationContext.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package localhost.login.util; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class InitApplicationContext { private static ApplicationContext context = null; private InitApplicationContext(){ } public static ApplicationContext getApplicationContext(){ if(context == null){ context = new ClassPathXmlApplicationContext("applicationContext.xml"); } return context; } } |
6.struts2相关
(1)建立用户登陆的action,为MVC的控制层(Controller)。
【UserLoginAction.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
package cn.no7player.ssh.action; import cn.no7player.ssh.po.User; import cn.no7player.ssh.service.UserService; import cn.no7player.ssh.util.InitApplicationContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import org.springframework.context.ApplicationContext; import java.util.List; /** * Created by zl on 1/22/2015. */ public class UserLoginAction extends ActionSupport{ private UserService userService; private User user; public UserLoginAction() { ApplicationContext context = InitApplicationContext.getApplicationContext(); userService = (UserService) context.getBean("userService"); } @Override public String execute() throws Exception { System.out.println(user.getName()); if (!isValid(user.getName())) { return INPUT; } if (!isValid(user.getPassword())) { return INPUT; } if(!userCheck(user)){ System.out.println("INPUT"); return INPUT; } System.out.println("SUCCESS"); ActionContext.getContext().getSession().put("user" , user); return SUCCESS; } public boolean isValid(String keyword) { return keyword != null && keyword != ""; } public boolean userCheck(User user) { List<User> userList = userService.findUserByName(user.getName()); if (userList == null || userList.size() < 1) { return false; } User checkUser = userList.get(0); System.out.println(checkUser.getName()); if (user.getName().equals(checkUser.getName()) && user.getPassword().equals(checkUser.getPassword())) { return true; } addActionError("Username or password is wrong, please check!"); return false; } public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } |
(2)配置struts.xml文件
【struts.xml】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?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> <package name="default" namespace="/" extends="struts-default"> <global-results> <result name="error">/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="error"/> </global-exception-mappings> <action name="login" class="cn.no7player.ssh.action.UserLoginAction"> <!-- 定义三个逻辑视图和物理资源之间的映射 --> <result name="input">/login.jsp</result> <result name="error">/error.jsp</result> <result name="success">/welcome.jsp</result> </action> </package> </struts> |
(3)配置web.xml文件,使其支持struts2
【web.xml】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Struts Blank</display-name> <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> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!--<listener>--> <!--<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>--> <!--</listener>--> </web-app> |
7.JSP相关
MVC的视图层(View)
(1)index.jsp 首页,登陆界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<%-- Created by IntelliJ IDEA. User: zl Date: 1/23/2015 Time: 9:15 AM To change this template use File | Settings | File Templates. --%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Log in</title> </head> <body> <s:form action="login" validate="true"> <s:textfield label="User Name" name="user.name" required="true"/> <s:password label="Password" name="user.password" required="true"/> <s:iterator value="errors"> <s:property/> </s:iterator> <s:submit value="login"/> </s:form> </body> </html> |
(2)welcome.jsp 登陆成功页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<%-- Created by IntelliJ IDEA. User: zl Date: 1/23/2015 Time: 9:15 AM To change this template use File | Settings | File Templates. --%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Hello</title> </head> <body> <h2>Welcome</h2> <s:if test="#session.user!=null"> <h2>Hello <s:property value="#session.user.name"/></h2> </s:if> </body> </html> |
(3)error.jsp 出错页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<%-- Created by IntelliJ IDEA. User: zl Date: 1/23/2015 Time: 9:44 AM To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title></title> </head> <body> <h2>Oh God,It's Wrong!</h2> </body> </html> |
三、单元测试
测试用例应该在编写每一个模块时一起完成,但为了前面操作的流畅性,这里就把测试代码单独放在这里了。
1.测试dao层
【UserDaoTest.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package cn.no7player.ssh.dao; import cn.no7player.ssh.po.User; import junit.framework.Assert; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class UserDaoTest extends TestCase { private ApplicationContext context = null; private User user = null; private UserDao userDAO = null; public void setUp() throws Exception { super.setUp(); context = new ClassPathXmlApplicationContext("applicationContext.xml"); userDAO = (UserDao)context.getBean("userDAO"); } public void tearDown() throws Exception { userDAO = null; user = null; } public void testAddUser() throws Exception { user = new User(); user.setName("username"); user.setPassword("password"); userDAO.addUser(user); Assert.assertNotNull(user.getId()); User userTwo = new User(); userTwo.setName("username1"); userTwo.setPassword("password"); userDAO.addUser(userTwo); Assert.assertNotNull( user.getId()); } public void testListAll() throws Exception { List<User> users = userDAO.listAll(); Assert.assertEquals(users.size(), 2); } } |
2.测试action
【UserLoginActionTest.java】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package cn.no7player.ssh.action; import cn.no7player.ssh.po.User; import cn.no7player.ssh.service.UserService; import cn.no7player.ssh.util.InitApplicationContext; import com.opensymphony.xwork2.Action; import junit.framework.Assert; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; public class UserLoginActionTest extends TestCase { private User user; private UserService userService; private ApplicationContext context = null; private UserLoginAction loginAction = null; public void setUp(){ context = InitApplicationContext.getApplicationContext(); loginAction = new UserLoginAction(); userService = (UserService)context.getBean("userService"); } //注:需要先执行UserDaoTest测试 public void testUserLogin(){ user = new User(); user.setName("username"); user.setPassword("password"); try { loginAction.setUser(user); loginAction.setUserService(userService); Assert.assertEquals(Action.SUCCESS, loginAction.execute()); user.setPassword("password1"); System.out.println(loginAction.getActionErrors()); Assert.assertEquals(Action.INPUT, loginAction.execute()); } catch (Exception e) { e.printStackTrace(); } } } |
四、总结
1.项目全部结构图
2.为了能正常登陆测试,数据库应该添加一些数据。
3.启动Tomcat,访问地址:http://localhost:8080/SS2HDemo/
按照博主的博文一步步进行,总体来说还是很顺利,但是数据库表的名称有误,导致一直查询不对,目前我也不知道类的名称是不是一定要和数据库表的名称一致,总之,把数据库的表的名称改为user之后就能顺利运行了
表示每一步都是按着做的,并没有成功。pom的依赖都是一样的。整个项目跑是跑起来了,但是一点击“login”就出来500错误,个人猜测是spring的配置文件没有加载,不管怎么样还是很感谢博主的精心编写。辛苦了。鞠躬
按照楼主的博文,终于搭建成功,我的jdk版本是1.8,需要修改java Target bytecode version为1.8