Struts是最早的Java开源框架之一,也是现在Java Web框架的事实标准。Struts是MVC设计模式一个优秀的实现。Struts定义了通用的Controller(控制器),通过配置文件(一般是struts-config.xml)隔离了Model(模型)和View(视图),以Action的概念对用户请求做了封装,使代码更清晰易读。到目前为止,Struts框架拥有两个主要的版本,分别为Struts1.x版本与Struts2.x版本,它们都是遵循MVC设计理念的开源Web框架。在2001年6月发布了Struts1.0版本,它是基于MVC设计理念而开发的Java Web应用框架。性能高效、松耦合、低侵入是程序开发人员追求的理想状态,针对Struts1框架中存在的缺陷与不足,全新的Struts2框架诞生,它改变了Struts1框架中的缺陷,而且还提供了更加灵活与强大的功能。
Spring的出现改变了Java世界。它的目标是使现有的JavaEE技术更易用和促进良好的编程习惯。它是一个轻量级的框架,渗透了JavaEE技术的方方面面。它主要作为依赖注入容器和AOP实现存在。还提供了声明事务、对DAO层的支持等简化开发的功能。Spring还可以很方便地与Struts、Hibernate等技术集成。
ORM(Object Relational Mapping)是对象到关系的映射,它的作用是在关系数据库和对象之间做一个自动映射,将数据库中数据表映射成为对象,也就是持久化类,对关系型数据以对象的形式进行操作,减少应用开发过程中数据持久化的编程任务。可以把ORM理解成关系型数据和对象的一个纽带,开发人员只需关注纽带的一端映射的对象即可。作为一个优秀的持久层框架,Hibernate充分体现了ORM的设计理念,提供了高效的对象到关系型数据库的持久化服务,它将持久化服务从软件业务层中完全抽取出来,让业务逻辑的处理更加简单,程序之间的各种业务并非紧密耦合,更加有利于高效地开发与维护。使开发人员在程序中可以利用面向对象的思想对关系型数据进行持久化操作,为关系型数据库和对象型数据打造了一个便捷的高速公路。
(1)下载Struts2框架包
Struts的官方网站 在该官方网站上可以获取Struts的所有版本及帮助文档,本文所使用的Struts2开发包为Struts2.5.20版本。
Struts2项目需要添加的类库文件:
(2)下载log4j-core-2.jar 包
log4j-core下载地址
在Struts2框架包中没有log4j-core-2.jar 包,需要自己下载。在src目录下添加log4j2.xml配置文件。
(1)下载Spring框架包
Spring框架包各版本的下载地址
(2)下载commons-logging.jar包
commons-logging.jar包下载地址
commons-logging只是一个高层的日志框架,本身没有实现真正的日志能力,它依赖其他的日志系统如log4j或者java本身的java.util.logging。可以通过配置文件来设定最终使用log4j还是java.util.logging。没有配置log4j的时候就会调用java.util.logging包。你可以可以通过配置在classpath根目录下log4j.properties来配置Log4j。
(3)下载aspectjweaver.jar包
aspectjweaver.jar包下载地址
aspectjweaver是spring AOP的切入点表达式需要用的包。spring配置中的
(1)下载Hibernate框架包
Hibernate官方网站
从Hibernate的官方网站获取所需的jar包,,在该网站可以免费获取Hibernate的帮助文档和jar包。
(2)下载JDBC数据库驱动
本示例以MySQL数据库为例。
MySQL数据库驱动的下载地址
关于搭建Hibernate开发环境的详细说明,请浏览本博客的文章:Hibernate搭建开发环境
包 | 说明 | 类型 | 创建类/接口 |
---|---|---|---|
com.pjb.ssh.dao | 数据库访问接口层 | 接口 | UserDao.java |
com.pjb.ssh.dao.impl | 数据库访问实现类层 | 类 | UserDaoImpl.java |
com.pjb.ssh.biz | 业务逻辑接口层 | 接口 | UserBiz.java |
com.pjb.ssh.biz.impl | 业务逻辑实现类层 | 类 | UserBizImpl.java |
com.pjb.ssh.entity | 实体层 | 类 | User.java User.hbm.xml |
com.pjb.ssh.model | 模型层 | 类 | UserModel.java |
com.pjb.ssh.util | 公共方法层 | 类 | UtilHelper.java |
com.pjb.ssh.action | Action层 | 类 | UserAction.java |
项目结构图如下:
创建com.pjb.ssh.entity包,并在该包下User.java(用户信息持久化类)和User.hbm.xml(Hibernate对象关系映射文件)
User.java(用户信息持久化类)代码如下:
package com.pjb.ssh.entity;
/**
* 用户信息持久化类
* @author pan_junbiao
**/
public class User
{
private int id; //用户编号
private String userName; //用户姓名
private String blogUrl; //博客地址
private int sex; //性别(1:男;2:女;)
private String provinceName; //省份
private String hobby; //兴趣爱好
private String remark; //备注
//默认的构造方法
public User() {
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String getBlogUrl()
{
return blogUrl;
}
public void setBlogUrl(String blogUrl)
{
this.blogUrl = blogUrl;
}
public int getSex()
{
return sex;
}
public void setSex(int sex)
{
this.sex = sex;
}
public String getProvinceName()
{
return provinceName;
}
public void setProvinceName(String provinceName)
{
this.provinceName = provinceName;
}
public String getHobby()
{
return hobby;
}
public void setHobby(String hobby)
{
this.hobby = hobby;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}
User.hbm.xml(Hibernate对象关系映射文件)配置信息如下:
创建com.pjb.ssh.dao包,并在该包下创建UserDao.java(用户信息数据库访问接口)。
package com.pjb.ssh.dao;
import com.pjb.ssh.entity.User;
import java.util.List;
/**
* 用户信息数据库访问接口
* @author pan_junbiao
**/
public interface UserDao
{
/**
* 新增用户信息
* @param user 用户对象
*/
public boolean save(User user);
/**
* 删除用户信息
* @param user 用户对象
*/
public boolean delete(User user);
/**
* 修改用户信息
* @param user 用户对象
*/
public boolean update(User user);
/**
* 获取用户信息
* @param id 用户ID
*/
public User get(int id);
/**
* 查询方法
* @param hql HQL语句
*/
public List find(String hql);
}
创建com.pjb.ssh.dao.impl包,并在该包下创建UserDaoImpl.java(用户信息数据库访问类),该类继承HibernateDaoSupport类和实现UserDao接口。
package com.pjb.ssh.dao.impl;
import com.pjb.ssh.dao.UserDao;
import com.pjb.ssh.entity.User;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import java.util.List;
/**
* 用户信息数据库访问类
* @author pan_junbiao
**/
public class UserDaoImpl extends HibernateDaoSupport implements UserDao
{
/**
* 新增用户信息
* @param user 用户对象
*/
@Override
public boolean save(User user)
{
boolean result = false;
try
{
super.getHibernateTemplate().save(user);
result = true;
}
catch (Exception e)
{
e.printStackTrace();
result = false;
}
return result;
}
/**
* 删除用户信息
* @param user 用户对象
*/
@Override
public boolean delete(User user)
{
boolean result = false;
try
{
super.getHibernateTemplate().delete(user);
result = true;
}
catch (Exception e)
{
e.printStackTrace();
result = false;
}
return result;
}
/**
* 修改用户信息
* @param user 用户对象
*/
@Override
public boolean update(User user)
{
boolean result = false;
try
{
super.getHibernateTemplate().update(user);
result = true;
}
catch (Exception e)
{
e.printStackTrace();
result = false;
}
return result;
}
/**
* 获取用户信息
* @param id 用户ID
*/
@Override
public User get(int id)
{
User result = null;
try
{
if (id <= 0)
{
return null;
}
result = super.getHibernateTemplate().get(User.class, id);
}
catch (Exception e)
{
e.printStackTrace();
result = null;
}
return result;
}
/**
* 查询方法
* @param hql HQL语句
*/
@Override
public List find(String hql)
{
return super.getHibernateTemplate().find(hql);
}
}
创建com.pjb.ssh.biz包,并在该包下创建UserBiz.java(用户信息业务逻辑接口)。
package com.pjb.ssh.biz;
import com.pjb.ssh.entity.User;
import java.util.List;
/**
* 用户信息业务逻辑接口
* @author pan_junbiao
**/
public interface UserBiz
{
/**
* 新增用户信息
* @param user 用户对象
*/
public boolean saveUser(User user);
/**
* 删除用户信息
* @param userId 用户ID
*/
public boolean deleteUser(int userId);
/**
* 修改用户信息
* @param user 用户对象
*/
public boolean updateUser(User user);
/**
* 获取用户信息
* @param userId 用户ID
*/
public User getUser(int userId);
/**
* 查询用户列表
*/
public List serchUserList();
}
创建com.pjb.ssh.biz.impl包,并在该包下创建UserBizImpl.java(用户信息业务逻辑类),该类实现UserBiz接口。
package com.pjb.ssh.biz.impl;
import com.pjb.ssh.dao.UserDao;
import com.pjb.ssh.biz.UserBiz;
import com.pjb.ssh.entity.User;
import java.util.List;
/**
* 用户信息业务逻辑类
* @author pan_junbiao
**/
public class UserBizImpl implements UserBiz
{
private UserDao userDao = null; //用户信息数据库访问类
public UserDao getUserDao()
{
return userDao;
}
public void setUserDao(UserDao userDao)
{
this.userDao = userDao;
}
/**
* 新增用户信息
* @param user 用户对象
*/
@Override
public boolean saveUser(User user)
{
boolean result = false;
//参数验证
if(user==null)
{
return false;
}
//新增用户信息
result = userDao.save(user);
return result;
}
/**
* 删除用户信息
* @param userId 用户ID
*/
@Override
public boolean deleteUser(int userId)
{
boolean result = false;
if (userId <= 0)
{
return false;
}
//获取用户对象
User user = userDao.get(userId);
if (user == null)
{
return false;
}
//删除用户对象
result = userDao.delete(user);
return result;
}
/**
* 修改用户信息
* @param user 用户对象
*/
@Override
public boolean updateUser(User user)
{
return userDao.update(user);
}
/**
* 获取用户信息
* @param userId 用户ID
*/
@Override
public User getUser(int userId)
{
return userDao.get(userId);
}
/**
* 查询用户列表
*/
@Override
public List serchUserList()
{
String hql = "FROM User user";
return userDao.find(hql);
}
}
创建com.pjb.ssh.util包,并在该包下创建UtilHelper.java(公共处理类)。
package com.pjb.ssh.util;
/**
* 公共处理类
*/
public class UtilHelper
{
/**
* 将数组转换成为字符串
*
* @param arr 字符串数组
* @param symbol 连接符号
* @return 字符串
*/
public static String arrToStr(String[] arr, String symbol)
{
// 实例化StringBuffer
StringBuffer sb = new StringBuffer();
// 判断arr是否为有效数组
if (arr != null && arr.length > 0)
{
// 遍历数组
for (String s : arr)
{
// 将字符串追加到StringBuffer中
sb.append(s);
// 将字符串追加到StringBuffer中
sb.append(symbol);
}
// 判断字符串长度是否有效
if (sb.length() > 0)
{
// 截取字符
sb = sb.deleteCharAt(sb.length() - 1);
}
}
// 返回字符串
return sb.toString();
}
}
创建com.pjb.ssh.model包,并在该包下创建UserModel.java(用户信息模型类)。
package com.pjb.ssh.model;
/**
* 用户信息模型类
* @author pan_junbiao
**/
public class UserModel
{
private int id; //用户编号
private String userName; //用户姓名
private String blogUrl; //博客地址
private int sex; //性别(1:男;2:女;)
private String provinceName; //省份
private String[] hobbyArray; //兴趣爱好(数组)
private String hobbyStr; //兴趣爱好(字符串)
private String remark; //备注
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String getBlogUrl()
{
return blogUrl;
}
public void setBlogUrl(String blogUrl)
{
this.blogUrl = blogUrl;
}
public int getSex()
{
return sex;
}
public void setSex(int sex)
{
this.sex = sex;
}
public String getProvinceName()
{
return provinceName;
}
public void setProvinceName(String provinceName)
{
this.provinceName = provinceName;
}
public String[] getHobbyArray()
{
return hobbyArray;
}
public void setHobbyArray(String[] hobbyArray)
{
this.hobbyArray = hobbyArray;
}
public String getHobbyStr()
{
return hobbyStr;
}
public void setHobbyStr(String hobbyStr)
{
this.hobbyStr = hobbyStr;
}
public String getRemark()
{
return remark;
}
public void setRemark(String remark)
{
this.remark = remark;
}
}
创建com.pjb.ssh.action包,并在该包下创建UserAction.java(用户Action类)。
package com.pjb.ssh.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.pjb.ssh.biz.UserBiz;
import com.pjb.ssh.entity.User;
import com.pjb.ssh.model.UserModel;
import com.pjb.ssh.util.UtilHelper;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用户Action类
* @author pan_junbiao
**/
public class UserAction extends ActionSupport implements ModelDriven, ServletRequestAware, ServletResponseAware
{
private static final long serialVersionUID = 1L;
private HttpServletRequest request; //Request对象
private HttpServletResponse response; //Response对象
UserBiz userBiz = null; //用户信息业务逻辑类
UserModel userModel = null; //用户信息模型类
public UserAction()
{
userModel = new UserModel();
}
// 获取Request对象
@Override
public void setServletRequest(HttpServletRequest var1)
{
this.request = var1;
}
// 获取Response对象
@Override
public void setServletResponse(HttpServletResponse arg0)
{
this.response = arg0;
}
@Override
public UserModel getModel()
{
return userModel;
}
public UserBiz getUserBiz()
{
return userBiz;
}
public void setUserBiz(UserBiz userBiz)
{
this.userBiz = userBiz;
}
public UserModel getUserModel()
{
return userModel;
}
public void setUserModel(UserModel userModel)
{
this.userModel = userModel;
}
/**
* 用户注册页面
*/
public String userRegisterView()
{
return INPUT;
}
/**
* 执行新增用户操作
*/
public String addUser()
{
String resultView = ERROR;
//参数验证
if (userModel.getUserName() == null || userModel.getUserName().equals(""))
{
return ERROR;
}
//将Model对象转换为实体对象
User user = new User();
user.setUserName(userModel.getUserName());
user.setBlogUrl(userModel.getBlogUrl());
user.setSex(userModel.getSex());
user.setProvinceName(userModel.getProvinceName());
user.setHobby(UtilHelper.arrToStr(userModel.getHobbyArray(), ";"));
user.setRemark(userModel.getRemark());
//调用业务逻辑层方法,执行新增操作
boolean resultExecute = userBiz.saveUser(user);
//返回结果页面
resultView = resultExecute ? SUCCESS : ERROR;
return resultView;
}
/**
* 获取用户信息
*/
public String userDetailView()
{
//获取用户ID参数
int userId = Integer.parseInt(request.getParameter("userId"));
//获取用户信息
User user = userBiz.getUser(userId);
if(user==null)
{
return ERROR;
}
//用户实体对象转换为Model对象
userModel.setId(user.getId());
userModel.setUserName(user.getUserName());
userModel.setBlogUrl(user.getBlogUrl());
userModel.setSex(user.getSex());
userModel.setProvinceName(user.getProvinceName());
userModel.setHobbyStr(user.getHobby());
userModel.setRemark(user.getRemark());
return "detail";
}
}
在Web项目的源码文件夹(src目录)中,创建名称为 log4j2.xml 的配置文件。
在Web项目的源码文件夹(src目录)中,创建名称为 applicationContext.xml 的配置文件(Spring框架的配置文件)。
com.mysql.cj.jdbc.Driver
jdbc:mysql://localhost:3306/db_admin?useSSL=false&serverTimezone=GMT%2b8
root
123456
org.hibernate.dialect.MySQL5Dialect
true
true
com/pjb/ssh/entity/User.hbm.xml
在Web项目的源码文件夹(src目录)中,创建名称为 struts.xml 的配置文件(Struts2框架的配置文件)。
regex:.*
user_register.jsp
user_detail.jsp
success.jsp
error.jsp
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
openSessionInViewFilter
org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
singleSession
false
openSessionInViewFilter
/*
struts2
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
struts2
/*
web.xml 配置说明:
(1)自动转载Spring配置信息
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
上述配置信息的作用是当Web容器启动时,自动装配 applicationContext.xml 配置文件(Spring框架的配置文件)。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
(2)解决Hibernate的LazyLoad(延时加载)问题的配置信息
openSessionInViewFilter
org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
singleSession
false
openSessionInViewFilter
/*
上述配置信息的作用是通过Spring的OpenSessionInViewFilter管理Hibernate的Session来解决LazyLoad(延时加载)的问题。
在hibernate中使用load方法时,并未把数据真正获取时就关闭了session,当我们真正想获取数据时会迫使load加载数据,而此时session已关闭,所以就会出现异常。 比较典型的是在MVC模式中,我们在M层调用持久层获取数据时(持久层用的是load方法加载数据),当这一调用结束时,session随之关闭,而我们希望在V层使用这些数据,这时才会迫使load加载数据,我们就希望这时的session是open着得,这就是所谓的Open Session In view 。 我们可以用filter来达到此目的。 这段话引至于百度百科,但确实很好的说明了OpenSessionInView这个过滤器的作用。
OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibernate的Session,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。 由于Hibernate引入了Lazy Load特性,使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoad的Exception。所以为了解决这个问题,Spring引入了这个Filter,使得Hibernate的Session的生命周期变长。
注意:这个filter一定要配置在struts的过滤器的前面,因为过滤器是“先进后出”原则,如果你配置在struts的后面的话,你的openSessionInView过滤器都执行完了,怎么在去在管理action的转向页面啊。
了解更多该配置信息的详细说明,请浏览本博客的文章:通过Spring的OpenSessionInViewFilter管理Hibernate的Session来解决LazyLoad(延时加载)的问题
(3)Struts2提供的过滤器
struts2
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
struts2
/*
Struts2框架主要通过一个过滤器将Struts集成到Web应用,通过这个过滤器对象,Struts2就可以获得Web应用中的HTTP请求,并将这个HTTP请求转发到指定的Action进行处理,Action根据处理的结果返回给客户端相应的页面。因此,在Struts2框架中,过滤器StrutsPrepareAndExecuteFilter是Web应用与Struts2 API之间的入口,它在Struts2应用中占有巨大的作用。
【实例】使用SSH框架,新增用户信息和获取用户信息。
在MySQL数据库中创建 tb_user(用户信息数据表),脚本如下:
-- 判断数据表是否存在,存在则删除
DROP TABLE IF EXISTS tb_user;
-- 创建“用户信息”数据表
CREATE TABLE IF NOT EXISTS tb_user
(
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',
blog_url VARCHAR(50) NOT NULL COMMENT '博客地址',
sex CHAR(2) DEFAULT '2' COMMENT '性别(1:男;2:女;)',
province_name VARCHAR(20) COMMENT '省份',
hobby VARCHAR(50) COMMENT '兴趣爱好',
remark VARCHAR(50) COMMENT '备注'
) COMMENT = '用户信息表';
执行结果如下:
(1)首页
(2)用户注册页面
(3)操作成功页面
程序代码:
(1)在UserAction.java(用户Action类)中编写进入用户注册页面和执行新增用户操作的方法。
/**
* 用户注册页面
*/
public String userRegisterView()
{
return INPUT;
}
/**
* 执行新增用户操作
*/
public String addUser()
{
String resultView = ERROR;
//参数验证
if (userModel.getUserName() == null || userModel.getUserName().equals(""))
{
return ERROR;
}
//将Model对象转换为实体对象
User user = new User();
user.setUserName(userModel.getUserName());
user.setBlogUrl(userModel.getBlogUrl());
user.setSex(userModel.getSex());
user.setProvinceName(userModel.getProvinceName());
user.setHobby(UtilHelper.arrToStr(userModel.getHobbyArray(), ";"));
user.setRemark(userModel.getRemark());
//调用业务逻辑层方法,执行新增操作
boolean resultExecute = userBiz.saveUser(user);
//返回结果页面
resultView = resultExecute ? SUCCESS : ERROR;
return resultView;
}
(2)创建 index.jsp(首页)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
首页
用户注册
用户详情
(2)创建 user_register.jsp(用户注册页面)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
用户注册
用户注册
(3)创建 success.jsp(操作成功页面)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
操作成功
恭喜,操作成功!
(4)创建 error.jsp(操作失败页面)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
操作失败
对不起,操作失败!
执行结果如下:
程序代码:
(1)在UserAction.java(用户Action类)中编写获取用户信息的方法。
/**
* 获取用户信息
*/
public String userDetailView()
{
//获取用户ID参数
int userId = Integer.parseInt(request.getParameter("userId"));
//获取用户信息
User user = userBiz.getUser(userId);
if (user == null)
{
return ERROR;
}
//用户实体对象转换为Model对象
userModel.setId(user.getId());
userModel.setUserName(user.getUserName());
userModel.setBlogUrl(user.getBlogUrl());
userModel.setSex(user.getSex());
userModel.setProvinceName(user.getProvinceName());
userModel.setHobbyStr(user.getHobby());
userModel.setRemark(user.getRemark());
return "detail";
}
(2)创建 user_detail.jsp(用户详情页面)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
用户详情
用户详情
- 用户名称:
- 博客地址:
- 性别:
男 女
- 省份:
- 爱好:
- 描述: