【化学药品管理平台——Struts2+Spring+Hibernate实现 0203】SSH后台业务
整合完SSH框架之后,我们开始重新编写后台代码。
先看用户后台。
UserDao
package com.rclv.dao.impl;
/*
* 2. 通过继承HibernateDaoSupport注入HibernateTemplate模板类
*/
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
// 1。set方法注入HibernateTemplate模板类
/*private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}*/
//分层开发持久层,用户注册,数据添加
@Override
public void registAtDao(User user){
/*Session session = HibernateUtils.getCurrentSession();
session.save(user);*/
this.getHibernateTemplate().save(user);
}
// 用户登陆,条件查询
@Override
public User getByNameAndPassword(String uname, String upassword){
String hql= "from User u where u.uname=? and u.upassword=?";
// find()方法条件查询,并判断ulist是否为空,若不为空则返回ulist的第一个参数。
List<User> ulist = (List<User>) this.getHibernateTemplate().find(hql, new String[]{uname, upassword});
if (ulist != null && ulist.size() > 0) {
return ulist.get(0);
}
return null;
}
}
我们先在dao层写好将要完成的数据库操作,由于该类中继承了HibernateDaoSupport接口,则可以获取HibernateTemplate对象直接用模板类封装好的方法操作数据库,或是获取SessionFactory对象进行原生的hibernate数据库操作,不过此时都已经不需要手动进行事务管理。
对于用户注册,获取HibernateTemplate模板类并调用其save()方法,直接进行数据添加,参数为service层传来的User对象。
对于用户登陆,写好hql条件查询语句,然后调用模板类的find()方法,传入uname和upassword参数代替hql中的占位符进行查询操作。因为find()方法的返回值是一个List集合,所以这里需要做一个list是否为空的判断,若list不为空,则返回list中的第一个User对象;否则返回一个null。
UserService
package com.rclv.service.impl;
@Transactional
public class UserServiceImpl implements UserService {
// 省略其他代码
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void regist(User user){
userDao.registAtDao(user);
}
@Override
public User login(String uname, String upassword){
return userDao.getByNameAndPassword(uname, upassword);
}
}
业务层直接调用dao层的方法。
UserAction
package com.rclv.web.action;
/**
* Servlet implementation class UserServlet
*/
public class UserAction extends ActionSupport implements ServletRequestAware, ModelDriven<User> {
HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
// User对象必须实例化
private User user = new User();
public User getModel() {
return user;
}
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
// 1.访问路径:http://localhost/cup_ssh2/user_registUI.action
public String registUI() {
// 2.返回值代表跳转到register.jsp页面
return "register";
}
// 用户注册,访问路径:http://localhost/cup_ssh2/user_regist.action
public String regist(){
user.setUid(UUIDUtils.getId());
user.setUpassword(MD5Utils.md5(user.getUpassword()));
userService.regist(user);
request.setAttribute("msg", "注册成功");
return "msg";
}
// 跳转到用户登陆页面,访问路径:http://localhost/cup_ssh2/user_loginUI.action
public String loginUI() throws ServletException, IOException {
return "login";
}
// 用户登陆,访问路径:http://localhost/cup_ssh2/user_login.action
public String login() throws Exception {
String uname = user.getUname();
String upassword = user.getUpassword();
upassword = MD5Utils.md5(upassword);
// 判断用户是否登陆成功
User user = userService.login(uname, upassword);
if (user == null) {
request.setAttribute("msg", "登录失败");
return "msg";
}
// 登陆成功将user设置到request域
request.getSession().setAttribute("user", user);
return "home";
}
// 用户退出,访问路径:http://localhost/cup_ssh2/user_logout.action
public String logout() throws Exception {
request.getSession().invalidate();
return "home";
}
}
对于用户注册,获取前台传入的User实体类,设置user的uid,加密其upassword,然后直接将user作为参数调用service层的regist(user)方法。
对于用户登陆,获取前台传入的参数,直接调用service层login(uname, upassword),然后判断该方法返回的user变量是否为空,若为空,则设置msg属性,跳转到msg.jsp页面;若不为空,则将user对象设置到request域中,并跳转到主页。
这里我们补充一个Action的通配符访问方式。
<!-- 配置包结构 -->
<package name="cupboard" extends="struts-default" namespace="/">
<global-results>
<result name="home">/jsp/home.jsp</result>
<result name="msg">/jsp/msg.jsp</result>
</global-results>
<!-- 分页展示action -->
<action name="list" class="agentsAction" method="list">
<result name="list">/jsp/agents_list.jsp</result>
</action>
<!-- 用户注册和用户登陆action -->
<action name="user_*" class="userAction" method="{1}">
<result name="register">/jsp/register.jsp</result>
<result name="login">/jsp/login.jsp</result>
</action>
</package>
使用通配符配置struts.xml,则访问路径要和方法名有某种联系。我们可以将用户action标签中的name属性值都赋为user_*,通配符*就代表可以是任意的字符,由前台的访问路径决定;而action标签中的method属性则设置为{1},表示和第一个通配符的取值相同。这样,UserAction中不同的方法就都可以配置在一个action标签中了。
使用通配符配置action访问的方式可以简化配置文件的代码编写,而且扩展和维护比较容易。
另外,<global-results>是全局结果集,可以被同一个<package>下的所有<action>使用。当一个Action类返回值没有相应的<result>时,Struts2就会查找全局结果集中的<result>。
再看药品后台。
AgentsDao
package com.rclv.dao.impl;
public class AgentsDaoImpl extends HibernateDaoSupport implements AgentsDao {
// 分页查询agents
@Override
public List<Agents> findAgentsByPage(int currPage, int pageSize) throws Exception {
// 获取SessionFactory,并打开一个Session,然后使用Query查询语句进行分页查询
Session session = this.getSessionFactory().openSession();
List<Agents> list = session.createQuery("from Agents order by adate desc").setFirstResult(((currPage-1)*pageSize)).setMaxResults(pageSize).list();
return list;
}
// HibernateTemplate模板类查询数据总数
@Override
public int getTotalCount() throws Exception {
String hql = "select count(*) from Agents as agents";
Long count = (Long) this.getHibernateTemplate().find(hql).listIterator().next();
return count.intValue();
}
// 药品入库,添加数据操作
@Override
public void add(Agents agents) throws Exception {
this.getHibernateTemplate().save(agents);
}
// 更新药品损耗
@Override
public void update(int oAid, int nCount) throws Exception {
String aid = String.valueOf(oAid);
// 根据aid条件查询agents,判断返回的list是否为空,若不为空,则对list中的第一个agents进行更新操作
List<Agents> agents = (List<Agents>) getHibernateTemplate().find("from Agents a where a.aid = ?", aid);
if(agents != null && agents.size() > 0) {
Agents agent = agents.get(0);
agent.setCount(nCount);
getHibernateTemplate().update(agent);
}
}
}
分页查询:获取SessionFactory,并打开一个Session,然后使用Query查询语句进行分页查询。因为Query查询语句的分页查询比HibernateTemplate模板类的分页查询写起来更简单,所以我们用Query.setFirstResult()方法和Query.setMaxResults()方法来进行分页查询。
总数查询:使用HibernateTemplate().find(hql).listIterator().next()方法查询药品总数。其实是先使用模板类的find()方法进行查询,使用迭代器对返回的List集合进行遍历,返回集合元素的总数。
药品入库:使用HibernateTemplate.save(agents)方法对传入的agents实体类进行数据添加操作。
药品损耗:根据aid条件查询agents,判断返回的list是否为空,若不为空,则对list中的第一个agents进行更新操作。
AgentsService
package com.rclv.service.impl;
@Transactional
public class AgentsServiceImpl implements AgentsService {
// 依赖注入
private AgentsDao agentsDao;
public void setAgentsDao(AgentsDao agentsDao) {
this.agentsDao = agentsDao;
}
// 分页查询
@Override
public PageBean<Agents> findAgentsByPage(int currPage, int pageSize) throws Exception {
//查询当前页数据
List<Agents> list=agentsDao.findAgentsByPage(currPage,pageSize);
//查询总条数
int totalCount = agentsDao.getTotalCount();
//返回一个PageBean对象
return new PageBean<>(list, currPage, pageSize, totalCount);
}
// 药品入库
@Override
public void add(Agents agents) throws Exception {
agentsDao.add(agents);
}
// 损耗更新
@Override
public void update(int oAid, int nCount) throws Exception {
agentsDao.update(oAid, nCount);
}
}
业务层直接调用dao层的方法。
AgentsAction
package com.rclv.web.action;
public class AgentsAction extends ActionSupport implements ServletRequestAware, ModelDriven<Agents>{
private AgentsService agentsService;
public void setAgentsService(AgentsService agentsService) {
this.agentsService = agentsService;
}
// set方法引入HttpServletRequest
private HttpServletRequest request;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
private Agents agents = new Agents();
@Override
public Agents getModel() {
return agents;
}
// 分页查询药品,访问路径:http://localhost/cup_ssh2/list.action
public String list() throws Exception {
// 1.从前台页面或Action中获取当前页码,并设置单页显示数量
int currPage = Integer.parseInt(request.getParameter("currPage"));
int pageSize=12;
//2.调用agentsService中的方法, 返回一个PageBean
PageBean<Agents> agentsBean=agentsService.findAgentsByPage(currPage,pageSize);
//3.将结果放入request中,请求转发
request.setAttribute("ab", agentsBean);
return "list";
}
// 添加药品,访问路径:http://localhost/cup_ssh2/agents_add.action
public String add() throws Exception {
// 1.获取session域中的User对象,若user为空,则跳转到msg.jsp页面
User user = (User) request.getSession().getAttribute("user");
if(user == null) {
request.setAttribute("msg", "请先登录");
return "msg";
}
// ConvertUtils.register(new MyConventer(), Date.class);
// 2.设置药品入库日期,并设置入库人
agents.setAdate(new Date());
agents.setUser(user);
// 3.调用service层方法,完成添加操作,并跳转
agentsService.add(agents);
return "alist";
}
// 损耗更新,访问路径:http://localhost/cup_ssh2/agents_update.action
public String update() throws Exception {
// 1.获取药品aid、药品原有数量、药品损耗数量
int oAid = Integer.parseInt(request.getParameter("oAid"));
int oCount = Integer.parseInt(request.getParameter("oCount"));
int dif = Integer.parseInt(request.getParameter("dif"));
// 2。计算现有数量
int nCount = oCount - dif;
// 3.调用service层方法完成更新操作,并跳转
agentsService.update(oAid, nCount);
return "alist";
}
}
分页查询:获取和设置currPage、pageSize参数,然后调用service层方法返回一个PageBean对象,并设置到request域中,返回到agents_list.jsp页面。
这里需要注意一点的是,currPage会从页面或Action中获取。因为当我们完成药品入库和损耗更新时,需要重新请求list.action进行分页查询,这时候需要从agents_add.action或是agents_update.action跳转到list.action,所以需要在struts.xml配置文件中,给agents_*.action的result标签中,配置一个currPage参数。
药品入库:这里先做一个用户是否登陆的判断,然后设置入库日期、设置入库人,调用service层方法完成数据添加操作。
损耗更新:获取前台传入的参数,根据现有药品数量和可损耗数量计算剩余数量,调用service层方法完成数据更新操作。
add()和update()方法的返回值都为alist,我们来看struts.xml配置文件。
<!-- 分页展示action -->
<action name="list" class="agentsAction" method="list">
<result name="list">/jsp/agents_list.jsp</result>
</action>
<!-- 药品入库和损耗,执行完Action,不保留当前action的request对象,跳转到name="list"的action -->
<action name="agents_*" class="agentsAction" method="{1}">
<!-- redirectAction表示不保留当前action的属性信息 -->
<result name="alist" type="redirectAction">
<param name="actionName">list</param>
<!-- 跳转list.action的同时,附上一个currPage参数 -->
<param name="currPage">1</param>
</result>
</action>
药品入库agents_add.action和损耗更新agents_update.action的result类型为redirectAction,表示将跳转到另外一个Action,而且是不保留当前action的request对象的跳转。根据param的actionName属性,将要跳转到list.action,跳转的同时传递一个currPage参数。如果不传递这个参数,将会报错,list()方法将无法从页面获取到currPage这个资源。
至此,我们完成了用SSH框架对Cupboard化学药品管理平台的开发。