一、项目环境的搭建
本项目所使用的软件和框架版本都已经包含在题目中。
1、搭建的流程最好为:
Spring --> Hibernate --> Spring和Hibernate的整合 --> Struts --> SSH整合
2、项目的架构(这是一个搭建好的能实现注册的项目):
3、项目的全部jar包
懒得去官网下载的可以看看,优快云自动设置的积分,没办法免费。
链接: https://download.youkuaiyun.com/download/qq_41135496/11225548.
二、框架理解
1、struts
从JSP界面接收的URL请求,都会被web.xml中设置的过滤器拦截并解析,比如struts-prepare、struts-execute等,谁在前谁先拦截
<filter-mapping>
<filter-name>struts-prepare</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts-execute</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
拦截解析出URL请求中包含的表单数据,根据表单数据要求使用的action调用action模型中的方法,最后根据方法返回的字符串调用另外的JSP界面或者
三、流程
1、Web Project的创建
因为Myeclipse2017中自带的Spring最高为4.1版本,所以我们的Hibernate也使用4.1版本,这里注意!!!,Spring4必须搭配JDK1.8
点击Next两次到这个界面
勾选第二个选项,自动创建web.xml文件,点击Next,在该界面取消勾选第二个选项,用不到JSTL这个库(JSP 标准标签库)。
然后点击Finish就完成了Web项目的创建。
2、Spring的导入
右键项目,选择Configure Facets,点击Install Spring Facet,点击Next直到到该界面,勾选Spring Persistence,Finish完成Spring包的导入。
3、Hibernate的导入
右键项目,选择Configure Facets,点击Install Hibernate Facet,在以下界面选择版本4.1
点击Next,在该界面取消勾选"Create SessionFactory class"
点击Next到该界面,选择自己配置好的DB Driver,Finish完成。
一建生成的applicationContext.xml还需要加上driverclass
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
配置好的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-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:tx="http://www.springframework.org/schema/tx">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url"
value="jdbc:oracle:thin:@localhost:1521:orcl">
</property>
<!--注意将value值更改为自己的用户名和密码-->
<property name="username" value="username"></property>
<property name="password" value="password"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" /></beans>
Spring和Hibernate暂时整合完毕了,接着就是不如写一个测试类验证一下,避免整个框架整合完成以后因为太过杂乱而不清楚错误出在哪里。
4、Hibernate逆向工程
先看一下数据库设计,以LogTab为例:
特别提醒:Oracle数据库在使用Hibernate的逆向工程时,主键自增只能选择Sequence,但Oracle中的sequence序列只能自己创建,SQL语句如下
-- Create sequence
create sequence LOGTAB_SEQ
minvalue 0
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
逆向工程如下,没有列出的界面直接Next跳过:
逆向生成的XML文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.model.Logtab" table="LOGTAB" schema="ZY">
<id name="logid" type="java.math.BigDecimal">
<column name="LOGID" precision="22" scale="0" />
<generator class="sequence" />
</id>
<property name="idnum" type="java.lang.Long">
<column name="IDNUM" precision="18" scale="0" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="PASSWORD" length="6" not-null="true" />
</property>
<property name="phonenum" type="java.lang.Long">
<column name="PHONENUM" precision="11" scale="0" not-null="true" />
</property>
</class>
</hibernate-mapping>
添加指定Sequence序列语句后如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="org.model.Logtab" table="LOGTAB" schema="ZY">
<id name="logid" type="java.math.BigDecimal">
<column name="LOGID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">logtab_seq</param>
</generator>
</id>
<property name="idnum" type="java.lang.Long">
<column name="IDNUM" precision="18" scale="0" not-null="true" />
</property>
<property name="password" type="java.lang.String">
<column name="PASSWORD" length="6" not-null="true" />
</property>
<property name="phonenum" type="java.lang.Long">
<column name="PHONENUM" precision="11" scale="0" not-null="true" />
</property>
</class>
</hibernate-mapping>
5、Test类
数据库中原来有这些数据
Test类代码
package Test;
import org.dao.DlDao;
import org.model.Logtab;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Logtab logtab = new Logtab();
logtab.setIdnum((long)888888888);
logtab.setPassword("888888");
logtab.setPhonenum((long)888888888);
ApplicationContext context = new
FileSystemXmlApplicationContext("src/applicationContext.xml");
DlDao dlDao = (DlDao) context.getBean("dlDao");
dlDao.save(logtab);
}
}
DlDao类代码
package org.dao;
import org.model.Logtab;
public interface DlDao {
public void save(Logtab logtab);
}
DlDaoImp类代码
package org.dao.imp;
import org.dao.DlDao;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.model.Logtab;
public class DlDaoImp implements DlDao{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Logtab logtab){
Session session = null;
Transaction ts = null;
try {
session = sessionFactory.openSession();
ts = session.beginTransaction();
session.save(logtab);
ts.commit();
} catch (Exception e) {
if(null!=ts)
ts.rollback();
throw new RuntimeException("保存數據出錯");
}finally {
if(null!=session)
session.close();
}
}
}
最后再来配置一下applicationContext.xml文件,把这个加进去
<bean id="dlDao" class="org.dao.imp.DlDaoImp">
<!-- property看做属性 -->
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
运行Test类后,数据库如下,插入成功:
6、添加Struts2框架
jar包官网可以下载
(1)在WebRoot下添加Struts2框架的核心包,这里添加的是2.5.10.1版本
(2)添加Spring支持包struts2-spring-plugin-2.5.10.jar
(3)在src下创建struts.xml文件
这里只用到注册部分,登录和注销暂时忽略,同时,这里注意一下版本部分,如果版本对不上程序会报错,这里使用2.5版本:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" extends="struts-default">
<!-- 注册 -->
<action name="register" class="userAction" method="register">
<result name="success">register_success.jsp</result>
</action>
<!-- 登录 -->
<action name="login" class="loginAction">
<result name="success">login_success.jsp</result>
<result name="error">login.jsp</result>
</action>
<!-- 注销 -->
<action name="logout" class="userAction" method="logout">
<result name="success">index.jsp</result>
</action>
</package>
</struts>
(4)创建消息包文件struts.properties
这是为了把Struts2的类的生成指定交给Spring完成
struts.objectFactory=spring
(5)修改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" id="WebApp_ID" version="3.1">
<filter>
<filter-name>struts-prepare</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareFilter</filter-class>
</filter>
<filter>
<filter-name>struts-execute</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-prepare</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts-execute</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
四、注册的实现
根据前三步的搭建,ssh的框架基本上已经搭建完成,我们用一个登录功能来验证一下:
1、数据流程
简单提一句,ssh框架学习中,需要掌握的数据流向有很多,比如注册中的JSP界面提交的数据存储到数据库中,登录中的从数据库查询数据,并且通常情况下我们都是从一个界面跳转到另一个界面,还存在着另一个需要掌握的,那就是请求转发和响应重定向,比如一个用户管理界面,实时注册了一个新用户,能不能界面不发生跳转将最新的用户信息在该界面陈列出来,这个我在以后的文章中会讲到。
按照数据走向来实现注册
对于一个新手来说,界面都不会写又怎么去写后端呢。
JSP --> Struts.xml --> applicationContext.xml -->
2、各文件源码
(1)JSP
login.jsp
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<div class="content">
<div class="right">
<div class="right_box">
<font face="宋体"></font><font face="宋体"></font><font face="宋体"></font><font face="宋体"></font>
<div class="banner"></div>
<div class="info_bk1">
<div align="center">
<form action="login.action" method="post" name="login">
用户登录<br>
身份证号:<input type="text" name="user.idNum" size= "20" id= "idnum"/><br>
密 码:<input type="password" name= "user.password" size="20" id="password"/><br>
手机号:<input type="text" name="user.phoneNum" size= "20" id= "phoneNum"/><br>
<input type="submit" value="登录"/>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
login_success.jsp
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<title>系统</title>
</head>
<body>
<h1>測試成功</h1>
</body>
</html>
(2)User.java
位于org.model.vo
当界面表单数据过多,并且在多处需要用到表单提交的数据的时候,单独将数据封装起来无疑是一个不错的选择。
package org.model.vo;
public class User {
private long idNum;
private String password;
private long phoneNum;
public long getIdNum() {
return idNum;
}
public void setIdNum(long idNum) {
this.idNum = idNum;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public long getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(long phoneNum) {
this.phoneNum = phoneNum;
}
}
(3)LoginAction.java
JSP界面通过action提交表单数据,Struts架构过滤器拦截URL请求,经过解析找到对应的action。
划重点:从这里开始,我们就真正开始了面向接口的编程
package org.action;
import org.model.Logtab;
import org.model.vo.User;
import org.service.DlService;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
//首先需要接收表单数据,实例化User对象
private User user = new User();
private DlService dlService;
public DlService getDlService() {
return dlService;
}
public void setDlService(DlService dlService) {
this.dlService = dlService;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//每一个Action类中都应该有一个execute()方法,这个方法对过滤器做出反应,返回一个字符串(记得用双引号)告诉struts.xml下一步应该调用哪个界面
@Override
public String execute() throws Exception {
//方法负责对数据表进行写入操作,应该对每个字段进行赋值
Logtab logtab = new Logtab();
//对传入的数据首先进行空值判断,避免写入的时候数据库报错
logtab.setIdnum(user.getIdNum());
logtab.setPassword(user.getPassword());
logtab.setPhonenum(user.getPhoneNum());
//写入操作需要调用业务层,也就是Service层
dlService.save(logtab);
return SUCCESS;
}
}
(4)DlServiceImp.java
package org.service.imp;
import org.dao.DlDao;
import org.model.Logtab;
import org.service.DlService;
import org.springframework.transaction.annotation.Transactional;
public class DlServiceImp implements DlService{
private DlDao dlDao;
public DlDao getDlDao() {
return dlDao;
}
public void setDlDao(DlDao dlDao) {
this.dlDao = dlDao;
}
@Transactional
@Override
public void save(Logtab logtab) throws RuntimeException {
dlDao.save(logtab);
}
}
(5)DlDaoImp.java
package org.dao.imp;
import org.dao.DlDao;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.model.Logtab;
public class DlDaoImp implements DlDao{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Logtab logtab){
Session session = null;
Transaction ts = null;
try {
session = sessionFactory.openSession();
ts = session.beginTransaction();
session.save(logtab);
ts.commit();
} catch (Exception e) {
if(null!=ts)
ts.rollback();
throw new RuntimeException("保存數據出錯");
}finally {
if(null!=session)
session.close();
}
}
}
(6)applicationContext.xml
面向接口编程在前几步已经根据调用顺序依次列出,action调用service,service调用dao,dao调用session,实际执行顺序我在其他文章中提到过依次,把图借来用一下,感兴趣的可以自己写几行打印代码测试一下:
Spring框架的作用之一就是接管实例化对象,在程序中用到什么组件向Spring工程索取,所以需要在配置文件中组装一下组件
<bean id="dlDao" class="org.dao.imp.DlDaoImp">
<!-- property看做属性 -->
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="dlService" class="org.service.imp.DlServiceImp">
<property name="dlDao">
<ref bean="dlDao"/>
</property>
</bean>
<bean id="loginAction" class="org.action.LoginAction" scope="prototype">
<property name="dlService">
<ref bean="dlService"/>
</property>
</bean>
完整配置文件如下,可直接复制:
<?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-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:tx="http://www.springframework.org/schema/tx">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url"
value="jdbc:oracle:thin:@localhost:1521:orcl">
</property>
<property name="username" value="username"></property>
<property name="password" value="password"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>org/model/Logtab.hbm.xml</value></list>
</property></bean>
<bean id="dlDao" class="org.dao.imp.DlDaoImp">
<!-- property看做属性 -->
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="dlService" class="org.service.imp.DlServiceImp">
<property name="dlDao">
<ref bean="dlDao"/>
</property>
</bean>
<bean id="loginAction" class="org.action.LoginAction" scope="prototype">
<property name="dlService">
<ref bean="dlService"/>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" /></beans>
3、运行结果