tags: SSH整合与阅读项目
前言
前面我们已经学习了怎么整合SSH框架了。是时候拿一个小项目来练练手了....我们现在要设计一个企业人事管理系统...
需求:
- **要求对员工信息进行维护; **
- 后台系统先登陆,才能操作员工: 添加/修改/删除
- 没有登陆,只能查看列表,不能操作!
功能分类:
- 【管理员模块】
- 注册/登陆
- 【员工模块】
-
- 添加一个员工, 指定添加的部门
-
- 对指定的员工信息修改
-
- 删除选择员工
-
- 列表展示
-
数据库设计
- 管理员表: t_admin
- 员工表: t_user
- 部门: t_dept
搭建配置环境
关于搭建配置环境可参考上一篇博文:blog.csdn.net/hon_3y/arti…
编写JavaBean 和映射文件#
JavaBean编写##
Admin.java
public class Admin {
private int id;
private String username;
private String password;
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
复制代码
User.java
public class User {
private int id;
private String username;
private Dept dept;
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 Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
复制代码
Dept.java
public class Dept {
private int id;
private String name;
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;
}
}
复制代码
映射文件##
Dept.hbm.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">
<hibernate-mapping package="zhongfucheng.entity">
<class name="Dept" table="t_dept">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
</class>
</hibernate-mapping>
复制代码
User.hbm.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">
<hibernate-mapping package="zhongfucheng.entity">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="username" column="userName"></property>
<many-to-one name="dept" class="Dept" column="dept_id"/>
</class>
</hibernate-mapping>
复制代码
Admin.hbm.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">
<hibernate-mapping package="zhongfucheng.entity">
<class name="Admin" table="t_admin">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="username" column="userName"></property>
<property name="password" column="password"></property>
</class>
</hibernate-mapping>
复制代码
编写Dao
编写BaseDao
为什么要写baseDao??可以参考我这篇博文:blog.csdn.net/hon_3y/arti…
package zhongfucheng.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.ParameterizedType;
import java.util.List;
/**
* Created by ozc on 2017/5/16.
*/
public abstract class BaseDao<T> {
// 容器注入sessionFactory
@Autowired
private SessionFactory sessionFactory;
//子类的类型
private Class<T> clazz;
//子类的名称
private String clazzName;
public BaseDao(){
clazz = (Class<T>) this.getClass(); //拿到的是子类
ParameterizedType pt = (ParameterizedType) clazz.getGenericSuperclass();
//拿到子类的真实类型
clazz = (Class) pt.getActualTypeArguments()[0];
//拿到子类的名称【HQL都是通过类名来查询的】
clazzName = clazz.getSimpleName();
}
public void add(T t){
sessionFactory.getCurrentSession().save(t);
}
public T find(String id){
return (T) sessionFactory.getCurrentSession().get(clazz, id);
}
public void update(T t){
sessionFactory.getCurrentSession().update(t);
}
public void delete(String id){
T t = (T) sessionFactory.getCurrentSession().get(clazz, id);
sessionFactory.getCurrentSession().delete(t);
}
public List<T> getAll() {
return sessionFactory.getCurrentSession().createQuery("from" + clazzName).list();
}
}
复制代码
编写UserDao
此时的UserDao已经有了baseDao的所有功能
/**
* 1.添加员工--->add()
* 2.修改员工--->find()
* 3.删除员工--->delete()
* 4.得到所有员工-->getAll()
* 5.根据id得到员工-->find()
* */
@Repository
public class UserDao extends BaseDao<User>{
}
复制代码
编写AdminDao
/**
*
* 1.保存管理员【注册】--->add()
* 2.查找管理员【登陆】--->login()
*
*
* */
@Repository
public class AdminDao extends BaseDao<Admin> {
@Autowired
private SessionFactory sessionFactory;
public Admin login(Admin admin) {
return (Admin) sessionFactory.
getCurrentSession().
createQuery("FROM Admin WHERE username=? AND password=?")
.setParameter(0, admin.getUsername())
.setParameter(1, admin.getPassword())
.uniqueResult();
}
}
复制代码
编写DeptDao
import org.springframework.stereotype.Repository;
import zhongfucheng.entity.Dept;
/**
* 1.查找所有的部门【在添加员工、修改员工时需要用】-->getAll()
* 2.通过id查找所在的部门信息--->find()
*
* */
@Repository
public class DeptDao extends BaseDao<Dept> {
}
复制代码
编写Service
UserService
@Transactional
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 1.添加员工--->add()
* 2.修改员工--->find()
* 3.删除员工--->delete()
* 4.得到所有员工-->getAll()
* 5.根据id得到员工-->find()
*/
public void addUser(User user) {
userDao.add(user);
}
public void updateUser(User user) {
userDao.update(user);
}
public void deleteUser(String id) {
userDao.delete(id);
}
public List<User> getAllUsers() {
return userDao.getAll();
}
public User findUserById(String id) {
return userDao.find(id);
}
}
复制代码
编写AdminService
@Transactional
@Service
public class AdminService {
@Autowired
private AdminDao adminDao;
/**
* 1.保存管理员【注册】--->save()
* 2.查找管理员【登陆】--->login()
*/
public void register(Admin admin) {
adminDao.add(admin);
}
public Admin login(Admin admin) {
return adminDao.login(admin);
}
}
复制代码
编写DeptService
@Transactional
@Service
public class DeptService {
@Autowired
private DeptDao deptDao;
/**
* 1.查找所有的部门【在添加员工、修改员工时需要用】-->getAll()
* 2.通过id查找所在的部门信息--->find()
*/
public List<Dept> getAllDept() {
return deptDao.getAll();
}
public Dept findDeptById(String id) {
return deptDao.find(id);
}
}
复制代码
员工模块
到目前为止,我们已经把后台的逻辑已经写完了,接下来就是写Action和前台的页面数据了。首先来写员工模块吧。
-
- 添加一个员工, 指定添加的部门
-
- 对指定的员工信息修改
-
- 删除选择员工
-
- 列表展示
列表展示
- UserAction
package zhongfucheng.action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.RequestAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import zhongfucheng.entity.User;
import zhongfucheng.service.UserService;
import java.util.List;
import java.util.Map;
/**
* Created by ozc on 2017/5/15.
*/
@Controller
@Scope("prototype")
public class UserAction extends ActionSupport implements RequestAware{
@Autowired
private UserService userService;
//因为多处用到request对象,那就直接实现接口,来得到request对象就行了
private Map<String, Object> request;
@Override
public void setRequest(Map<String, Object> map) {
this.request = map;
}
/*列表展示*/
public String list() {
List<User> list = userService.getAllUsers();
System.out.println(list);
//把数据封装到request对象上
request.put("list", list);
return "list";
}
}
复制代码
Struts配置文件
<action name="user_*" class="userAction" method="{1}">
<!--列表展示-->
<result name="list">/list.jsp</result>
</action>
复制代码
list.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>列表展示</title>
</head>
<body>
<s:if test="#request.list != null">
<table align="center" border="1">
<tr>
<td>员工编号</td>
<td>员工姓名</td>
<td>员工部门编号</td>
<td>操作</td>
</tr>
<s:iterator var="user" value="#request.list" status="st">
<tr>
<td><s:property value="#user.id"/></td>
<td><s:property value="#user.username"/></td>
<td><s:property value="#user.dept.id"/> </td>
<td><s:a href="#"> 修改,删除</s:a></td>
</tr>
</s:iterator>
</table>
</s:if>
<s:else>对不起,还没有员工的信息,请录入</s:else>
</body>
</html>
复制代码
效果:
添加员工
添加员工,指定添加部门,跳转到添加员工显示页面...
@Autowired
private DeptService deptService;
/*添加员工...给出添加的JSP页面*/
public String viewAdd() {
//在添加员工的时候需要得到所有的部门信息
List<Dept> deptList = deptService.getAllDept();
//封装到request域对象中
request.put("deptList", deptList);
return "viewAdd";
}
复制代码
<!--给出添加员工的界面-->
<result name="viewAdd">/viewAdd.jsp</result>
复制代码
显示添加员工界面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>添加员工界面</title>
</head>
<body>
<s:form method="POST" action="user_addUser.action" theme="simple">
<table align="center" border="1">
<tr>
<td>员工名称</td>
<td><s:textfield name="username" id="username" value=""/></td>
</tr>
<tr>
<td>员工部门</td>
<!--
Struts下拉列表标签:
name="deptId" 下拉列表标签的名称(服务器根据这个名称获取选择的项的实际的值value值)
headerKey 默认选择项的实际的值
headerValue 默认下拉列表显示的内容
list 下拉列表显示数据的集合
listKey 集合对象的哪个属性作为下拉列表的实例的值,即value值
listValue 集合对象的哪个属性作为下拉列表显示的值
value 默认选择的项的设置
-->
<td><s:select list="#request.deptList" headerKey="-1" headerValue="请选择" listKey="id" listValue="name" name="deptId"/></td>
</tr>
<tr>
<td colspan="2"><s:submit value="添加员工"/></td>
</tr>
</table>
</s:form>
</body>
</html>
复制代码
- 在Action中使用模型驱动和数据自动封装来获取JSP页面带过来的数据:
//模型驱动
User user = new User();
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public Object getModel() {
return user;
}
//自动封装deptId
private int deptId;
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
复制代码
- 找到要添加员工的部门,设置员工与部门的关系。添加到数据库中:
/*添加员工*/
public String addUser() {
//根据部门id查找部门对象
Dept dept = deptService.findDeptById(deptId);
//设置部门与员工的关系
user.setDept(dept);
userService.addUser(user);
//返回列表展示
return "listPage";
}
复制代码
- 返回到列表展示页面
<!--返回列表展示页面-->
<result name="listPage" type="redirectAction">user_list</result>
复制代码
- 效果:
修改员工
- 修改与删除的超链接:指明要修改用户的id【不然服务器哪知道你点击了哪一个用户】
<td>
<s:a href="user_viewUpdate?id=%{#user.id}">修改</s:a>
<s:a href="user_delete?id=%{#user.id}"> 删除</s:a>
</td>
复制代码
- 提供修改界面【其实就是回显数据】
/*为修改提供页面,其实就是回显数据*/
public String viewUpdate() {
//得到user
User user = userService.findUserById(this.user.getId());
//得到所有的部门
List<Dept> deptList = deptService.getAllDept();
request.put("deptList", deptList);
//使用Struts2的回显技术
ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.pop();
valueStack.push(user);
return "viewUpdate";
}
复制代码
<!--提供修改页面-->
<result name="viewUpdate">/viewUpdate.jsp</result>
复制代码
- 修改页面JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>修改员工界面</title>
</head>
<body>
<s:form method="POST" action="user_updateUser.action" theme="simple">
<table align="center" border="1">
<%--这里要把id通过隐藏域带过去--%>
<s:hidden name="id" id="id" value="%{id}"/>
<tr>
<td>员工名称</td>
<td><s:textfield name="username" id="username"/></td>
</tr>
<tr>
<td>员工部门</td>
<td>
<s:select name="deptId"
list="#request.deptList"
listKey="id"
listValue="name"
value="dept.id"/>
</td>
</tr>
<tr>
<td colspan="2"><s:submit value="修改员工"/></td>
</tr>
</table>
</s:form>
</body>
</html>
复制代码
- 因为使用了模型驱动,那么Action会把JSP带过来的数据直接封装到user对象中,我们直接使用即可
/*确认修改员工,模型驱动会把数据直接封装到user对象中*/
public String updateUser() {
//得到部门
Dept dept = deptService.findDeptById(deptId);
//设置员工与部门的关系
user.setDept(dept);
userService.updateUser(user);
//修改完,返回展示列表
return "listPage";
}
复制代码
- 效果:
删除员工
/*删除员工*/
public String delete() {
userService.deleteUser(user.getId());
//修改完,返回展示列表
return "listPage";
}
复制代码
- 测试:
管理员模块
- 注册
- 登陆
注册
- 提供注册的超链接
<s:a href="register.jsp">注册</s:a>
复制代码
- Admin.action
package zhongfucheng.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import zhongfucheng.entity.Admin;
import zhongfucheng.service.AdminService;
/**
* Created by ozc on 2017/5/15.
*/
@Controller
@Scope("prototype")
public class AdminAction extends ActionSupport implements ModelDriven<Admin>{
/**********调用service**************/
@Autowired
private AdminService adminService;
/**************使用模型驱动******************/
Admin admin = new Admin();
public Admin getAdmin() {
return admin;
}
public void setAdmin(Admin admin) {
this.admin = admin;
}
@Override
public Admin getModel() {
return admin;
}
}
复制代码
- 配置信息
<!--############管理员模块#################-->
<action name="admin_*" class="adminAction" method="{1}">
</action>
复制代码
- JSP页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册界面</title>
</head>
<body>
<s:form action="admin_register" method="POST" theme="simple">
<table border="1" align="center">
<tr>
<td>管理员账号:</td>
<td><s:textfield name="username"/></td>
</tr>
<tr>
<td>管理员密码:</td>
<td><s:textfield name="password"/></td>
</tr>
<tr>
<td colspan="2"><s:submit value="注册"/> </td>
</tr>
</table>
</s:form>
</body>
</html>
复制代码
- Action实现
/*得到JSP页面带过来的数据、完成注册*/
public String register() {
adminService.register(admin);
return "listPage";
}
复制代码
- 效果:
登陆功能
- 提供登陆的超链接
<s:a href="login.jsp">登陆</s:a>
复制代码
- 登陆的JSP页面
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆界面</title>
</head>
<body>
<s:form action="admin_login" method="POST" theme="simple">
<table border="1" align="center">
<tr>
<td>管理员账号:</td>
<td><s:textfield name="username" value=""/></td>
</tr>
<tr>
<td>管理员密码:</td>
<td><s:textfield name="password" value=""/></td>
</tr>
<tr>
<td colspan="2"><s:submit value="登陆"/> </td>
</tr>
</table>
</s:form>
</body>
</html>
复制代码
- Action中处理登陆
/*完成登陆*/
public String login() {
adminService.login(admin);
//把用户保存在Sessiion中
ActionContext.getContext().getSession().put("admin", admin);
return "listPage";
}
复制代码
- 在list页面给出相对应的提示,如果登陆了就给出欢迎的显示
<s:if test="#session.admin !=null">
欢迎您:<s:property value="%{#session.admin.username}"/>
</s:if>
复制代码
- 效果:
权限操作
- 后台系统先登陆,才能操作员工: 添加/修改/删除
- 没有登陆,只能查看列表,不能操作!
我们写一个拦截器,判断是否调用登陆或者列表展示的方法,如果不是就查看该用户有没有登陆。没有登陆就跳转到登陆界面
package zhongfucheng.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* Created by ozc on 2017/5/17.
*/
public class PrivilegeInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
//得到ActionContext
ActionContext context = actionInvocation.getInvocationContext();
//得到正在调用Action的方法名
String methodName = actionInvocation.getProxy().getMethod();
//获取session中管理员的对象
Object o = context.getSession().get("admin");
//判断正在调用什么方法
if ("login".equals(methodName) || "list".equals(methodName)) {
//调用了这两个方法,不用权限,直接调用把
return actionInvocation.invoke();
} else {
//如果不是,那么检查
// 没有登陆,就跳转到登陆界面呗
if (o == null) {
return "login";
} else {
// 有登陆,那么就可以执行呗
return actionInvocation.invoke();
}
}
}
}
复制代码
- 在Struts2配置文件中配置拦截器
<!-- 拦截器配置 -->
<interceptors>
<interceptor name="userInterceptor" class="cn.itcast.action.UserInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="userInterceptor"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 执行指定的拦截器 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>
复制代码
- 拦截器返回的login需要配置全局视图
<global-results>
<!--回到展示列表页面-->
<result name="listPage" type="redirectAction">user_list</result>
<!--拦截器返回login-->
<result name="login" type="redirect">/login.jsp</result>
</global-results>
复制代码
- 效果:
总结
本篇主要使用SSH框架来开发一个比较简易的CRUD项目。让我们熟悉SSH框架开发的流程。
- 设计实体
- 编写每个实体的映射文件
- 把映射文件加载到Hibernate中管理起来
- 使用BaseDao来管理全部的Dao,使得每个Dao都有Curd的方法。这样就不用我们在每个Dao都写上Crud了
- 如果普通的CURD方法满足不了我们,就可以在特定的Dao中写上自己想要的功能
- Service层调用Dao层的方法
- Controller调用Service层的方法实现功能,如果页面上需要后天的数据的话,那么我们先调用service获取得到数据,然后通过域对象(值栈对象)把数据存储起来,在页面上做展示。
如果您觉得这篇文章帮助到了您,可以给作者一点鼓励