【化学药品管理平台——spring MVC+Spring+MyBatis实现 0303】SSM后台业务
整合完SSM框架之后,我们开始重新编写后台代码。
先看用户后台。
项目文件结构
UserMapper.java
package com.rclv.dao;
public interface UserMapper {
// 用户注册
public void regist(User user);
// 用户登陆
public User getByNameAndPassword(String uname, String upassword);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.rclv.dao.UserMapper">
<!-- 用户注册 -->
<insert id="regist" parameterType="com.rclv.pojo.User" >
insert into user (uid, uname, upassword, ugrade) values(#{uid},#{uname},#{upassword},#{ugrade})
</insert>
<!-- 用户登陆 -->
<select id="getByNameAndPassword" parameterType="string" resultType="com.rclv.pojo.User">
select * from user u where u.uname=#{0} and u.upassword=#{1}
</select>
</mapper>
先创建UserMapper动态代理实现Dao接口,并创建和其对应的UserMapper.xml映射文件。映射文件中,分别在映射插入语句标签<insert>和映射查询语句标签<select>中创建了用户注册插入语句和用户登陆查询语句,通过#{}符号设置sql语句的参数。
这里需要注意的是,getByNameAndPassword()接口有两个相同类型的输入参数,则在映射文件的查询语句中,需要用#{0}和#{1}分别表示两个输入参数。
UserService
package com.rclv.service;
/**
* 组件自动扫描机制,可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入Spring容器中管理。
*/
@Service
public class UserServiceImpl implements UserService {
/*
* @Autowired注释,可以对类成员变量、方法及构造函数进行标注,进行自动装配完成spring注入。 @Autowired的使用可以替代set、get方法。
* 这里自动装配了UserMapper接口,程序会从spring容器中查找组件扫描配置的UserMapper动态代理对象,付给UserMapper接口。
*/
@Autowired
private UserMapper userMapper;
// 调用UserMapper动态代理接口完成用户注册操作。
@Override
public void regist(User user){
userMapper.regist(user);
}
// 调用UserMapper动态代理接口完成用户登陆操作。
@Override
public User login(String uname, String upassword) throws Exception{
return userMapper.getByNameAndPassword(uname, upassword);
}
}
业务层直接调用UserMapper接口中的方法,Mybatis会进行动态代理的实现。
UserController
package com.rclv.controller;
/**
* 组件自动扫描机制,可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入Spring容器中管理。
*/
@Controller
@RequestMapping("/user")
public class UserController{
/*
* @Autowired注释,可以对类成员变量、方法及构造函数进行标注,进行自动装配完成spring注入。 @Autowired的使用可以替代set、get方法。
* 这里自动装配了UserService类,程序会从spring容器中查找组件扫描配置的UserService实现类对象,付给UserService类。
*/
@Autowired
private UserService userService;
// 跳转到注册页面。访问路径:http://localhost/cup_ssm/user/registUI.action
@RequestMapping("/registUI")
public String registUI() {
return "register";
}
// 用户注册。访问路径:http://localhost/cup_ssm/user/regist.action
@RequestMapping("/regist")
public String regist(User user, HttpServletRequest request){
user.setUid(UUIDUtils.getId());
user.setUpassword(MD5Utils.md5(user.getUpassword()));
userService.regist(user);
request.setAttribute("msg", "注册成功");
return "msg";
}
// 跳转到登陆页面。访问路径:http://localhost/cup_ssm/user/loginUI.action
@RequestMapping("/loginUI")
public String loginUI() throws ServletException, IOException {
return "login";
}
// 用户登陆。访问路径:http://localhost/cup_ssm/user/login.action
@RequestMapping("/login")
public String login(User user, HttpServletRequest request) throws Exception {
String uname = user.getUname();
String upassword = user.getUpassword();
upassword = MD5Utils.md5(upassword);
// 判断用户是否登陆成功
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_ssm/user/logout.action
@RequestMapping("/logout")
public String logout(HttpServletRequest request) throws Exception {
request.getSession().invalidate();
return "home";
}
}
UserController类中的regist()和login()方法都绑定了User和HttpServletRequest两个参数。
对于用户注册,获取前台传入的User实体类,设置user的uid,加密其upassword,然后直接将user作为参数调用service层的regist(user)方法。
对于用户登陆,获取前台传入的参数,直接调用service层login(uname, upassword),然后判断该方法返回的user变量是否为空,若为空,则设置msg属性,跳转到msg.jsp页面;若不为空,则将user对象设置到request域中,并跳转到主页。
AgentsMapper.java
package com.rclv.dao;
public interface AgentsMapper {
// 分页查询agents
public List<Agents> findAgentsByPage(int firstIndex, int pageSize) throws Exception; /*{
Session session = getSessionFactory().openSession();
List<Agents> list = session.createQuery("from Agents order by adate desc").setFirstResult(((currPage-1)*pageSize)).setMaxResults(pageSize).list();
return list;
}*/
// 查询数据总数
public int getTotalCount() throws Exception; /*{
String hql = "select count(*) from Agents as agents";
return ((Long)getSessionFactory().openSession().createQuery(hql).uniqueResult()).intValue();
}*/
// 药品入库,添加数据操作
public void add(Agents agents) throws Exception; /*{
this.getHibernateTemplate().persist(agents);
}*/
// 更新药品损耗
public void update(int oAid, int nCount) throws Exception; /*{
String aid = String.valueOf(oAid);
List<Agents> agents = (List<Agents>) getHibernateTemplate().find("from Agents a where a.aid = ?", aid);
agents.get(0).setCount(nCount);
getHibernateTemplate().update(agents.get(0));
}*/
public void addImags(Agents agents) throws Exception; /*{
getHibernateTemplate().saveOrUpdate(agents);
}*/
}
AgentsMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.rclv.dao.AgentsMapper">
<!-- agents与user多对一的关联关系,作为返回结果集 -->
<resultMap type="com.rclv.pojo.Agents" id="agentsAndUserResultMap">
<!-- id标签指定主键字段对应关系
column:列,数据库中的字段名称
property:属性,java中pojo中的属性名称
-->
<id column="aid" property="aid"/>
<result column="aname" property="aname"/>
<result column="aimg" property="aimg"/>
<result column="aboard" property="aboard"/>
<result column="aNo" property="ano"/>
<result column="aCAS" property="acas"/>
<result column="aspec" property="aspec"/>
<result column="count" property="count"/>
<result column="aunit" property="aunit"/>
<result column="astore" property="astore"/>
<result column="asup" property="asup"/>
<result column="adate" property="adate"/>
<!-- result:标签指定非主键字段的对应关系 -->
<!-- 这个标签指定单个对象的对应关系
property:指定将数据放入Agents中的user属性中
javaType:user属性的类型
-->
<association property="user" javaType="com.rclv.pojo.User">
<id column="uid" property="uid"/>
<result column="uname" property="uname"/>
<result column="upassword" property="upassword"/>
<result column="ugrade" property="ugrade"/>
</association>
<!-- MyBatis中的一对多和对多一 关系需要设定一个resultMap标签,并在其中分别设定以下两个标签
association:多对一的关系,该标签中对应的是一方
collection:一对多的关系,改标签中对应的是多方
-->
</resultMap>
<!-- 分页查询agents -->
<select id="findAgentsByPage" parameterType="int" resultMap="agentsAndUserResultMap">
select * from agents a, user u where a.uid = u.uid order by adate desc, aid desc limit #{0},#{1}
</select>
<!-- 查询数据总数 -->
<select id="getTotalCount" resultType="int">
select count(*) from agents
</select>
<!-- 药品入库,添加数据操作 -->
<insert id="add" parameterType="com.rclv.pojo.Agents" >
insert into agents (aid, aname, aimg, aboard, aNo, aCAS, aspec, count, aunit, astore, asup, adate, uid)
values(#{aid},#{aname},#{aimg},#{aboard},#{ano},#{acas},#{aspec},#{count},#{aunit},#{astore},#{asup},#{adate},#{user.uid})
</insert>
<!-- 更新药品损耗 -->
<update id="update" parameterType="int">
update agents a set a.count = #{1} where a.aid = #{0}
</update>
</mapper>
先创建AgentsMapper动态代理实现Dao接口,并创建和其对应的UserMapper.xml映射文件。映射文件中,创建了映射查询语句、映射插入语句、映射更新语句,分别对应药品分页查询、药品总数查询、药品入库和药品损耗更新。
这里需要注意的是,由于agents和user是多对一的关系,查询agents需要关联查询出user,所以需要单独创建一个resultMap返回结果集。
resultMap标签:
type:多方类全名
id:唯一标识agentsAndUserResultMap
id标签:指定主键字段对应关系
column:数据库中的字段名称
property:java中pojo中的属性名称
association标签:设定一方参数
property:数据库中一方表名称
javaType:user属性的类型
这样一来,在<select id="findAgentsByPage">分页查询映射语句标签中将resultMap的属性值设为agentsAndUserResultMap,即表示返回类型为设定好的多对一关系结果集,可以完成关联查询。
AgentsService
package com.rclv.service;
@Service
public class AgentsServiceImpl implements AgentsService {
// 注解形式的依赖注入
@Autowired
private AgentsMapper agentsMapper;
// 分页查询
@Override
public PageBean<Agents> findAgentsByPage(int currPage, int pageSize) throws Exception {
// 计算当前页首个数据的位置,并查询当前页数据
int firstIndex = (currPage-1)*pageSize;
List<Agents> list=agentsMapper.findAgentsByPage(firstIndex, pageSize);
// 查询总条数
int totalCount = agentsMapper.getTotalCount();
// 返回一个PageBean对象
return new PageBean<>(list, currPage, pageSize, totalCount);
}
// 药品入库
@Override
public void add(Agents agents) throws Exception {
agentsMapper.add(agents);
}
// 损耗更新
@Override
public void update(int oAid, int nCount) throws Exception {
agentsMapper.update(oAid, nCount);
}
@Override
public void addImgs(Agents agents) throws Exception {
agentsMapper.addImags(agents);
}
}
业务层直接调用dao层的方法。
这里需要注意的是,和前面个两个版本不同的是,之前都是在Dao层计算出当前页首个数据的位置,而在SSM框架中,因为不方便在AgentsMapper.xml映射文件中进行计算,所以在service层计算。
AgentsController
package com.rclv.controller;
@Controller
@RequestMapping("/agents")
public class AgentsController {
// @Autowired形式注入AgentsService。
@Autowired
private AgentsService agentsService;
// 分页查询药品。访问路径:http://localhost/cup_ssm/agents/list.action
@RequestMapping("/list")
public String list(HttpServletRequest request) throws Exception {
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 "agents_list";
}
// 添加药品。访问路径:http://localhost/cup_ssm/agents/add.action
@RequestMapping("/add")
public String add(User user, Agents agents, HttpServletRequest request) throws Exception {
// 1.获取session域中的User对象,若user为空,则跳转到msg.jsp页面
user = (User) request.getSession().getAttribute("user");
if(user == null) {
request.setAttribute("msg", "请先登录");
return "msg";
}
// 2.设置药品入库日期,并设置入库人
agents.setAdate(new Date());
agents.setUser(user);
// 3.调用service层方法,完成添加操作,并重定向到list.action
agentsService.add(agents);
return "redirect:/agents/list.action?currPage=1";
}
// 损耗更新。访问路径:http://localhost/cup_ssm/agents/update.action
@RequestMapping("/update")
public String update(HttpServletRequest request) 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层方法完成更新操作,并重定向到list.action
agentsService.update(oAid, nCount);
return "redirect:/agents/list.action?currPage=1";
}
}
分页查询:获取和设置currPage、pageSize参数,然后调用service层方法返回一个PageBean对象,并设置到request域中,返回到agents_list.jsp页面。
药品入库:这里先做一个用户是否登陆的判断,然后设置入库日期、设置入库人,调用service层方法完成数据添加操作。
损耗更新:获取前台传入的参数,根据现有药品数量和可损耗数量计算剩余数量,调用service层方法完成数据更新操作。
这里需要注意的是,执行添加商品和更新损耗之后,要跳转到分页查询action,所以这里将add()和update()方法的返回值写成"redirect:/agents/list.action?currPage=1",以完成从一个controller跳转到另一个controller。
至此,我们完成了用SSM框架对Cupboard化学药品管理平台的开发,也完成了Jsp+Servlet、SSH、SSM三种方式对此项目的开发。学以致用,从此项目开始策划到完成,到完成博客的撰写,已经过了五六个月。博主将暂时停下写博客,继续学习其他的技术,并加强计算机基础技能,希望得到更多朋友的关注。