前言:此次项目仅仅只是我学习SSH框架时的一个入门实例,本身没有太复杂的东西。同时这篇文章也算是对所学知识的一个总结和梳理,当然能够帮到一些初学Java的ssh框架的童鞋就更好了。大神轻喷,文中有误的话可以在下方留言。(PS:文末有整个项目的源代码和相关sql文件的下载链接)
这个项目很简单,只是做一个简单的用户登录即可。由于我没有使用Myeclipse开发,而是使用了eclipse for Java EE来开发,因此所做的步骤相对要多一点O(∩_∩)O~
一 Spring整合Hibernate并测试
1 在MySQL5中创建数据库bookshop,并运行bookshop.sql,导入相关的表和数据
2 创建一个Dynamic Web Project �C> “ssh2test1”,导入jar包(所有jar包均存放在WebContent/WEB-INF/lib),接下来创建一个包“com.ssh2test1.entity”,用于存放相关实体类以及配置文件。有关实体类的介绍可自行参考Hibernate相关内容。由于是用户登录,因为我们需要用到数据库中的 users这个表。所以接下来就是在com.ssh2test1.entity里创建一个Users.java和它的配置文件Users.hbm.xml:
Users.java:
package com.ssh2test1.entity; import java.io.Serializable; public class Users implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String loginName; private String loginPwd; private String name; private String address; private String phone; private String mail; private Integer userRoleId; private Integer userStateId; public Users(){ } public Users(Integer id, String loginName, String loginPwd, String name, String address, String phone, String mail, Integer userRoleId, Integer userStateId) { super(); this.id = id; this.loginName = loginName; this.loginPwd = loginPwd; this.name = name; this.address = address; this.phone = phone; this.mail = mail; this.userRoleId = userRoleId; this.userStateId = userStateId; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPwd() { return loginPwd; } public void setLoginPwd(String loginPwd) { this.loginPwd = loginPwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } public Integer getUserRoleId() { return userRoleId; } public void setUserRoleId(Integer userRoleId) { this.userRoleId = userRoleId; } public Integer getUserStateId() { return userStateId; } public void setUserStateId(Integer userStateId) { this.userStateId = userStateId; } }
Users.hbm.xml:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.ssh2test1.entity.Users" table="users" catalog="bookshop"> <id name="id" type="java.lang.Integer"> <column name="Id" /> <generator class="native" /> </id> <property name="loginName" type="java.lang.String"> <column name="LoginName" length="50" /> </property> <property name="loginPwd" type="java.lang.String"> <column name="LoginPwd" length="16" /> </property> <property name="name" type="java.lang.String"> <column name="Name" length="16" /> </property> <property name="address" type="java.lang.String"> <column name="Address" length="16" /> </property> <property name="phone" type="java.lang.String"> <column name="Phone" length="16" /> </property> <property name="mail" type="java.lang.String"> <column name="Mail" length="16" /> </property> <property name="userRoleId" type="java.lang.Integer"> <column name="UserRoleId" /> </property> <property name="userStateId" type="java.lang.Integer"> <column name="UserStateId" /> </property> </class> </hibernate-mapping>
3 配置proxool数据库连接池
(1) 在src根目录下创建一个proxool.xml,用于配置数据库连接情况,下面附上代码,里面有详细注释
proxool.xml:
<?xml version="1.0" encoding="UTF-8"?> <something-else-entirely> <proxool> <alias>ProxoolPool</alias> <driver-url>jdbc:mysql://127.0.0.1:3306/bookshop?useUnicode=true&characterEncoding=utf-8</driver-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <driver-properties> <property name="user" value="root"/> <property name="password" value="root"/> </driver-properties> <!--最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 --> <maximum-connection-count>100</maximum-connection-count> <!--最小连接数(默认2个)--> <minimum-connection-count>10</minimum-connection-count> <!--proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁默认30秒--> <house-keeping-sleep-time>90000</house-keeping-sleep-time> <!--没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受--> <maximum-new-connections>10</maximum-new-connections> <!--最少保持的空闲连接数(默认2个)--> <prototype-count>5</prototype-count> <!--在使用之前测试--> <test-before-use>true</test-before-use> <!--用于保持连接的测试语句 --> <house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql> </proxool> </something-else-entirely>
(2) 配置web.xml,注意:在Spring中配置proxool连接池和在Hibernate中配置有很大的不同,一般情况下proxool再web.xml中是这样配置的:
<servlet> <servlet-name>proxoolServletConfigurator</servlet-name> <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF/classes/proxool.xml</param-value><!--这里对应刚才建立的xml配置文件名--> </init-param> <load-on-startup>1</load-on-startup> </servlet>
但是又因为Spring通过Listener方式启动,这就导致了Spring比proxool先加载,然后程序运行时将会报错:
(7073 ms) [ERROR] [11:40:40] org.logicalcobwebs.proxool.ProxoolDriver �C Problem
org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its alias ‘ProxoolPool’
at org.logicalcobwebs.proxool.ConnectionPoolDefinition.doChange(ConnectionPoolDefinition.java:246)
at org.logicalcobwebs.proxool.ConnectionPoolDefinition.<init>(ConnectionPoolDefinition.java:143)
at org.logicalcobwebs.proxool.ProxoolFacade.registerConnectionPool(ProxoolFacade.java:96)
at org.logicalcobwebs.proxool.ProxoolDriver.connect(ProxoolDriver.java:77)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
因此在这里我们需要proxool也以listener启动,并且还比Spring先启动即可。有大神写了个补丁,我把它命名为ProxoolListener.jar放在lib下了,下面附上现在的web.xml配置情况
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- proxool改成了以listener方式启动,加载了一个自定义的 ProxoolListener.jar --> <context-param> <param-name>proxoolConfigLocation</param-name> <param-value>WEB-INF/classes/proxool.xml</param-value> </context-param> <listener> <listener-class>org.logicalcobwebs.proxool.configuration.ListenerConfigurator</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/classes/applicationContext.xml</param-value> </context-param> <!-- 指定以Listener方式启动 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 以下3项参数与log4j的配置相关 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>WEB-INF/classes/log4j.properties</param-value> </context-param> <!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond--> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <!-- Web 项目 Spring 加载 Log4j 的监听 --> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <!-- struts2 --> <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>
(3) 在src根目录下新建applicationContext.xml,用于配置相关数据源和实例对象,以实现依赖关系的注入。在这里先配置proxool数据源和sessionFactory
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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 配置数据源,proxool数据库连接池 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName" value="org.logicalcobwebs.proxool.ProxoolDriver" /> <!-- proxool配置文件中的别名要一致 --> <property name="url" value="proxool.ProxoolPool" /> </bean> <!-- 配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <!-- 加载实体配置文件 --> <value>com/ssh2test1/entity/Users.hbm.xml</value> </list> </property> </bean> </beans>
4 创建一个包“com.ssh2test1.dao”,封装的是数据库操作。里面有一个接口UserDAO.java和它的实现类UserDAOImpl.java
UserDAO.java:
package com.ssh2test1.dao; import java.util.List; import com.ssh2test1.entity.Users; public interface UserDAO { public List<Users> search(Users user); }
UserDAOImpl.java:
package com.ssh2test1.dao; import java.util.List; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.orm.hibernate5.HibernateCallback; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import com.ssh2test1.entity.Users; public class UserDAOImpl extends HibernateDaoSupport implements UserDAO { public List<Users> search(Users user) { Object execute = super.getHibernateTemplate().execute(new HibernateCallback<Object>() { public Object doInHibernate(Session session) throws HibernateException{ Query query = null; if(user != null){ if(user.getLoginName() != null && !user.getLoginName().equals("") && user.getLoginPwd() != null && !user.getLoginPwd().equals("")){ String hql = "from Users user where user.loginName = :loginName and user.loginPwd = :loginPwd"; query = session.createQuery(hql); query.setString("loginName", user.getLoginName()); query.setString("loginPwd", user.getLoginPwd()); } } return query.list(); } }); return (List)execute; } }
5 创建一个包“com.ssh2test1.biz”,这是业务逻辑层,里面有一个接口“UserBiz.java”和它的实现类“UserBizImpl.java”,封装了登录操作
UserBiz.java:
package com.ssh2test1.biz; import java.util.List; import com.ssh2test1.entity.Users; public interface UserBiz { public List<Users> login(Users user); }
UserBizImpl.java:
package com.ssh2test1.biz; import java.util.List; import com.ssh2test1.dao.UserDAO; import com.ssh2test1.entity.Users; public class UserBizImpl implements UserBiz { //依赖注入 UserDAO userDAO; public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public List<Users> login(Users user) { return userDAO.search(user); } }
6 在applicationContext.xml里面添加UserDAO和UserBiz的实例,在上面的配置后面添加节点:
<!-- UserDAO实例 --> <bean id="userDAO" class="com.ssh2test1.dao.UserDAOImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- UserBiz实例 --> <bean id="userBiz" class="com.ssh2test1.biz.UserBizImpl"> <property name="userDAO" ref="userDAO"/> </bean>
7 Spring和Hibernate的整合到这里差不多就可以了,接下来在WebContent里新建testHibernateSpring.jsp,对前面的配置进行测试:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="org.springframework.context.ApplicationContext"%> <%@page import="org.springframework.context.support.ClassPathXmlApplicationContext"%> <%@page import="com.ssh2test1.biz.UserBiz"%> <%@page import="com.ssh2test1.entity.Users"%> <%@page import="java.util.List"%> <% ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserBiz userBiz = (UserBiz) context.getBean("userBiz"); Users user = new Users(); user.setLoginName("admin"); user.setLoginPwd("admin"); List list = userBiz.login(user); if(list.size() > 0) System.out.println("登录成功"); else System.out.println("登录失败"); %>
如果启动项目后运行testHibernateSpring.jsp文件显示上图这样的提示,则说明我们上面的Spring+Hibernate整合配置已经成功了
二 Spring整合Struts2并测试
1 编写视图页面login.jsp和login_success.jsp
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <base href="<%=basePath%>"> <title>用户登录</title> </head> <body> <div align="right"> <s:a href=""> <h5><font color="blue">还未注册?点击注册</font></h5> </s:a> </div><br><br> <div align="center" style="color:#6DA500"> <s:form action="login" method="post"> <s:textfield name="username" label="账号"></s:textfield> <s:textfield name="password" label="密码"></s:textfield> <s:submit value="登录"></s:submit> </s:form> </div> </body> </html>
login_success.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <base href="<%=basePath%>"> <title>我的主页</title> </head> <body> <h4 align="right"><font color="blue">欢迎您,${user }</font></h4> </body> </html>
2 web.xml里添加Struts2过滤器
<!-- struts2 --> <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>
3 在applicationContext.xml中添加Struts2的Action的实例
<!-- UserManagerAction实例 --> <bean id="umAction" class="com.ssh2test1.action.UserManagerAction"> <property name="userBiz" ref="userBiz" /> </bean>
4 在src根目录下新建struts.xml,并配置。注意的是,在这里class属性不再使用类的全名,而是使用applicationContext.xml中定义的Action的Bean实例名称
struts.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.action.extension" value="do,action"></constant> <constant name="struts.i18n.encoding" value="utf-8"></constant> <package name="default" extends="struts-default"> <action name="login" class="umAction"> <result name="error">login.jsp</result> <result name="success" type="redirect">login_success.jsp</result> </action> </package> </struts>
5 新建包“com.ssh2test1.action”,并创建一个Action类“UserManagerAction.java”,调用userBiz里的login()方法进行登录判断
UserManagerAction.java:
package com.ssh2test1.action; import java.util.List; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.ssh2test1.biz.UserBiz; import com.ssh2test1.entity.Users; public class UserManagerAction extends ActionSupport { private static final long serialVersionUID = 1L; private String username,password; UserBiz userBiz; 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; } public void setUserBiz(UserBiz userBiz) { this.userBiz = userBiz; } public String execute()throws Exception{ Users user = new Users(); user.setLoginName(username); user.setLoginPwd(password); List<Users> list = userBiz.login(user); if(list.size() > 0){ ActionContext context = ActionContext.getContext(); Map<String, Object> session = context.getSession(); session.put("user", username); return SUCCESS; } else return ERROR; } }
6 整个项目的配置步骤到此结束,现在启动项目后运行login.jsp进行测试,用户名:admin,密码:admin。如果登录成功后显示下图这样的页面,则表示全部配置已经成功了
附:源代码和SQL文件下载链接:http://down.51cto.com/data/2122558
(PS:如果没有下载豆的话,可以看我个人博客上的这篇文章,里面有百度云盘的链接。传送门:最新版使用ssh框架(struts2-x-spring4-x-hibernate5-x)搭建javaweb开发环境实例)