【化学药品管理平台——Servlet+Jsp实现 0103】后台药品

   本项目最后一篇博文,讲药品后台。

 

JavaBean

   药品部分涉及到两个JavaBean,一个Agents药品,一个PageBean<E>按页查询。

   先看Agents对象。

package com.rclv.domain;

import java.util.Date;

public class Agents {
	
	private String aid;		// 药品Id
	
	private String aname;		// 品名
	private String aimg;		// 图片
	private String aboard;		// 品牌
	
	private String aNo;		// 货号
	private String aCAS;		// CAS号
	private String aspec;		// 规格
	
	private Integer count;		// 数量
	private String aunit;		// 单位
	private String astore;		// 存放地
	
	private String asup;		// 供应商
	private Date adate;		// 入库日期
	private User user;		// 聚合一个User对象,代表入库人
        // 省略set、get方法
}

   Agents中的成员变量都是药品的一些属性,最后一个变量是聚合了一个User对象,作为当前药品的入库人。我们需要记录是哪个用户入库了某个药品,所以通过聚合实现一个单向关联的关系,即用户和药品是一对多的关系。

   再看PageBean<E>。

package com.rclv.domain;

public class PageBean<E> {
	private List<E> list;			// 封装Agents
	private Integer currPage;		// 当前页码
	private Integer pageSize;		// 每页显示数量
	private Integer totalPage;		// 总页数
	private Integer totalCount;		// 数据总数量
	
	// 省略其他set、get方法
	
	public Integer getTotalPage() {
		return (int)Math.ceil(totalCount*1.0/pageSize);
	}
	
	public PageBean() { }
	
	public PageBean(List<E> list, Integer currPage, Integer pageSize, Integer totalCount) {
		super();
		this.list = list;
		this.currPage = currPage;
		this.pageSize = pageSize;
		this.totalCount = totalCount;
	}
	
}

   PageBean的作用是实现分页查询,其中的成员变量是些和页码相关的属性,并聚合了List<E>泛型类存储主要的查询数据。PageBean的总页数totalPage由totalCount和pageSize计算出:return (int)Math.ceil(totalCount*1.0/pageSize)。

   (1)按页查询药品

package com.rclv.web.servlet;

public class AgentsServlet extends BaseServlet {
	
    // 分页展示药品
    public String findAgentsByPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
	//1.返回当前页数,并设置每页显示总个数
	int currPage=Integer.parseInt(request.getParameter("currPage"));
	int pageSize=12;
		
	//2.调用service,返回pagebean
	AgentsService as = (AgentsService) BeanFactory.getBean("AgentsService");
	PageBean<Agents> agentsBean=as.findAgentsByPage(currPage,pageSize);
		
	//3.将结果放入request中 请求转发
	request.setAttribute("ab", agentsBean);
	return "/jsp/agents_list.jsp";
    }
}

   控制层。

   第一步。获取前台当前页码currPage,并设置每页显示数量pageSize。

   第二步。调用service层方法,findAgentsByPage(currPage,pageSize),查询药品,并返回一个PageBean<Agents>对象agentsBean。

   第三步。将agentsBean属性设置到request域中,并请求转发到agents_list.jsp页面。

package com.rclv.service.impl;

public class AgentsServiceImpl implements AgentsService {

    @Override
    public PageBean<Agents> findAgentsByPage(int currPage, int pageSize) throws Exception {
	AgentsDao ad = (AgentsDao) BeanFactory.getBean("AgentsDao");
	// 1.调用dao层,查询返回当前页数据
	List<Agents> list=ad.findAgentsByPage(currPage,pageSize);
		
	// 2.调用dao层,查询返回所有药品总数量
	int totalCount = ad.getTotalCount();
		
	// 3.传入所有实参,返回新建PageBean。
	return new PageBean<>(list, currPage, pageSize, totalCount);
    }
}

   业务层。

   第一步。调用dao层findAgentsByPage(currPage,pageSize)方法,查询返回参数为Agents的List集合。

   第二步。调用dao层getTotalCount()方法,查询返回药品总数量totalCount。

   第三步。传入所有实参,返回新建PageBean。

package com.rclv.dao.impl;

public class AgentsDaoImpl implements AgentsDao {
	
    @Override
    public List<Agents> findAgentsByPage(int currPage, int pageSize) throws Exception {
	// 1.创建QueryRunner对象qr并连接数据库,创建sql查询语句
	QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
	String sql = "select * from agents order by adate desc limit ?,?";
	// 2.执行数据库查询,方法第二个参数表示要返回一个参数为Agents的List集合
	List<Agents> list = qr.query(sql, new BeanListHandler<>(Agents.class), (currPage-1)*pageSize, pageSize);
		
	// 3.循环遍历,对list中的每一个Agents对象再次进行查询操作。查询aid为当前agents.aid的agents内连接user后的数据,
	// 并返回为一个List<Map<String, Object>>集合。
	for (Agents agents : list) {
		sql = "select * from agents a, user u where a.uid = u.uid and a.aid = ?";
		List<Map<String, Object>> mlist = qr.query(sql, new MapListHandler(), agents.getAid());
		for (Map<String, Object> map : mlist) {
			// 4.新建User对象,并将map集合内所有的键值映射到user中对应的属性。最后以set方法将user添加到agents中。
			User user = new User();
			BeanUtils.populate(user, map);
			agents.setUser(user);
		}
	}
		
        return list;
    }
	
    // 查询agents的总数
    @Override
    public int getTotalCount() throws Exception {
	// 1.创建数据库连接,查询语句为聚合函数查询agents总数量。
	QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
	String sql = "select count(*) from agents";
		
	// 2.ScalarHandler用来查询封装单个结果值,返回值为Object类型,所以在这里先强转为Long型,再转为int类型。
	return ((Long)qr.query(sql, new ScalarHandler())).intValue();
    }
}	

   持久层。

   findAgentsByPage(currPage,pageSize)方法。

   第一步。创建QueryRunner对象qr并连接数据库,创建sql查询语句,根据agents表中的adate降序排序,limit限定查询数量。

   第二步。调用qr.query(sql, new BeanListHandler<>(Agents.class), (currPage-1)*pageSize, pageSize)方法进行数据库查询,方法第二个参数表示要返回一个参数为Agents的List集合,第三、四个参数替代sql语句的占位符,表示查询从当前页第一个数据开始的pageSize个数据。

   第三步。foreach循环语句。对list中的每一个Agents对象再次进行查询操作。查询语句sql表示查询aid为当前agents.aid的agents内连接user后的数据,并返回为一个List<Map<String, Object>>集合。其实mlist中只有一个Map集合,但是我们依然用foreach语句操作其中的Map集合。

   第四步。新建一个User对象。用BeanUtils.populate(user, map)方法,将上一步中查询到的内联数据map集合内所有的键值映射到user中对应的属性。最后用set方法将user添加到agents中。

   第四步的目的就是给agents设置user变量值,只是过程麻烦了点,需要一次内敛查询、一次映射封装和一次set方法。

 

   getTotalCount()方法。

   第一步。创建数据库连接,查询语句为聚合函数查询agents总数量。

   第二步。执行数据库查询操作。qr.query(sql, new ScalarHandler())用来查询封装单个结果值,返回值为Object类型,所以在这里先强转为Long型,再转为int类型。

 

   至此,分页查询后台功能完成,我们再回到前台。

<!-- jstl的forEach语句展示EL获得从后台传来的数据 -->
<tbody>
	<c:forEach items="${ab.list }" var="a">
	<tr>
		<td>${a.aname }</td>
		<!-- 鼠标悬停放大图片,以及点击添加图片 -->
		<td class="picsTd">
		    <div id="picsMagnify">
			<!-- 此处省略 -->
			<input name="${a.aname }" value="${a.aid }" style="display: none;" />
		    </div>
		</td>
		<td>${a.aboard}</td>
		<td>${a.aNo}</td>
		<td>${a.aCAS}</td>
		<td>${a.aspec}</td>
		<td>${a.count}</td>
		<td>${a.aunit}</td>
		<td>${a.astore}</td>
		<td>${a.asup}</td>
		<td>${a.user.uname}</td>
		<td>${a.adate}</td>
		<!-- 点击修改药品损耗情况 -->
		<td>
			<button type="button" class="btn btn-default" name="${a.aid }" value="${a.count}" onclick="showDiv(this)" >损耗</button>
		</td>
	</tr>
	</c:forEach>
<tbody>
<!--分页查询 -->
<div style="width:380px;margin:0 auto;margin-top:20px;">
    <ul class="pagination" style="text-align:center; margin-top:10px;">
	<!-- 判断当前页是否是首页  -->
	<c:if test="${ab.currPage == 1 }">
            <li class="disabled">
		<a href="javascript:void(0)" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a>
	    </li>
        </c:if>
        <!-- 此处省略 -->
    </ul>
</div>
<!-- 分页结束-->

   后台查询返回的PageBean对象添加到了request域中的ab属性,前台agents_list.jsp中,用EL表达式${ab.list }取出PageBean中的List集合,用forEach表达式展示list中的agents各属性。另外,${ab.currPage }用做当前页的判断。

 

   (2)药品入库

// 商品入库
	public String add(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 1.判断用户是否登陆,未登陆先跳转
		User user = (User) request.getSession().getAttribute("user");
		if(user == null) {
			request.setAttribute("msg", "请先登录");
			return "/jsp/msg.jsp";
		}
		
		// 2.将前端传来的数据放入map集合,然后封装到一个Agents类里
		Map<String, String[]> map = request.getParameterMap();
		Agents agents = new Agents();
		BeanUtils.populate(agents, map);
		
		// ConvertUtils.register(new MyConventer(), Date.class);
		// 3.给agents实例设置日期和用户属性
		agents.setAdate(new Date());
		agents.setUser(user);
		
		// 4.调用service完成药品入库功能,并重定向到按页查询的Servlet请求
		AgentsService as = (AgentsService) BeanFactory.getBean("AgentsService");
		as.add(agents);
		response.sendRedirect(request.getContextPath() + "/agents?method=findAgentsByPage&currPage=1");
		
		return null;
	}

   控制层。

   第一步。判断用户是否登陆,若未登录,则设置msg属性值,并跳转到msg.jsp消息页面。

   第二步。用Map集合获取前台传入的所有入库药品信息,新建Agents对象,将map中的键值映射到agents中。

   第三步。给agents设置当前时间和当前用户。

   第四步。调用AgentsService.add(Agents agents)方法进入service层。最后,重定向到按页查询的Servlet请求。

 

   业务层。

   这里直接调用AgentsDao.add(Agents agents)方法进入dao层。

// 完成数据库增加操作
@Override
public void add(Agents agents) throws Exception {
	// 1.连接数据库,创建查询语句为插入语句,用占位符表示要添加的字段值。
	QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
	String sql = "insert into agents values(?,?,?,?,?,?,?,?,?,?,?,?,?)";
	
	// 2.qr.update()方法执行数据库插入操作,其中的参数通过获取Agents的变量值来传参,对应sql语句占位符。
	qr.update(sql, agents.getAid(), agents.getAname(), agents.getAimg(),
			agents.getAboard(), agents.getaNo(), agents.getaCAS(),
			agents.getAspec(), agents.getCount(), agents.getAunit(),
			agents.getAstore(), agents.getAsup(), agents.getAdate(),
			agents.getUser().getUid());
}

   持久层。

   第一步。连接数据库,创建查询语句为插入语句,用占位符表示要添加的字段值。

   第二步。qr.update()方法执行数据库插入操作,其中的参数通过获取Agents的变量值来传参,对应sql语句占位符。

 

   至此,完成药品入库的后台功能。

 

   (3)药品损耗

// 更新药品损耗
public String update(HttpServletRequest request, HttpServletResponse response) 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.计算药品损耗后的数量,调用service完成数量跟新
	int nCount = oCount - dif;
	AgentsService agents = (AgentsService) BeanFactory.getBean("AgentsService");
	agents.update(oAid, nCount);
	
	// 3.重定向到按页查询的Servlet请求
	response.sendRedirect(request.getContextPath() + "/agents?method=findAgentsByPage&currPage=1");
	return null;
}

   控制层。

   第一步。获取药品Id、原数量和损耗量。

   第二步。计算损耗后的数量,并调用AgentsService.update(int oAid, int nCount)方法进入service层。

   第三步。重定向到按页查询的Servlet请求。

 

   业务层。

   直接调用AgentsDao.update(int oAid, int nCount)方法进入dao层。

 

   控制层。

   根据药品id完成简单的条件更新操作。

 

   (4)添加或更新图片

package com.rclv.web.servlet;

public class AddImageServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		try {
			// 1.创建map 放入前台传递的数据
			HashMap<String, Object> map = new HashMap<>();
			
			// 2.创建磁盘文件项
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 3.创建核心上传对象
			ServletFileUpload upload = new ServletFileUpload(factory);
			// 4.解析request,返回List集合,参数为FileItem类
			List<FileItem> list = upload.parseRequest(request);

			// 4.foreach遍历集合
			for (FileItem fi : list) {
				// 5.判断是否是普通的上传组件
				if(fi.isFormField()){
					// 普通上传组件
					// 将key-value放入map中
					map.put(fi.getFieldName(),fi.getString("utf-8"));
				}else{
					// 6.文件上传组件
					// 6.1获取文件名称
					String name = fi.getName();
					
					// 6.2获取文件的真实名称
					String realName = UploadUtils.getRealName(name);
					// 6.3获取文件的随机名称
					String uuidName = UploadUtils.getUUIDName(realName);
					
					// 7.获取文件的存放路径
					String path = this.getServletContext().getRealPath("/aimg/1");
					
					// 8.获取文件输入流
					InputStream is = fi.getInputStream();
					// 9.创建输出流
					FileOutputStream os = new FileOutputStream(new File(path, uuidName));
					
					// 10.将输入流数据复制到输出流,并关闭输入输出流
					IOUtils.copy(is, os);
					os.close();
					is.close();
					
					// 11.删除临时文件
					fi.delete();
					
					// 12.在map中设置图片的路径
					map.put(fi.getFieldName(), "aimg/1/"+uuidName);
					
				}
				
			}
			
			// 13.新建Agents对象,并将map的键值映射到agents中。
			Agents agents = new Agents();
			BeanUtils.populate(agents, map);
			
			// 14.调用AgentsService.addImgs(Agents agents)方法进入dao层。
			AgentsService as = (AgentsService) BeanFactory.getBean("AgentsService");
			as.addImgs(agents);
			
			// 15.重定向到按页查询的Servlet请求
			response.sendRedirect(request.getContextPath() + "/agents?method=findAgentsByPage&currPage=1");
		} catch (Exception e) {
			e.printStackTrace();
			request.setAttribute("msg", "商品添加失败~");
			request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);
			return;
		}
		
		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

   控制层。

   AddImageServlet没有继承BaseServlet,而是直接继承HttpServlet,并重写doGet方法来完成图片上传功能。

   第一步。创建Map集合,用来传入前台传递的数据。

   第二步。创建磁盘文件项DiskFileItemFactory类对象。

   第三步。创建ServletFileUpload核心上传对象。

   第四步。解析request,返回List集合,参数为FileItem类。

   第五步。foreach遍历list集合中的FileItem对象fi。判断fi是否是普通的上传组件,若是,则直接将fi的key-value放入map中。

   第六步。fi是文件上传组件。则获取fi文件名称,再获取文件真是名称,再转为UUID随机名称。

   第七步。this.getServletContext().getRealPath("/aimg/1")方法获取文件存放路径。此路径为apache项目部署路径。

   第八步。获取文件输入流InputStream类对象。

   第九步。创建文件输出流FileOutputStream类对象。

   第十步。通过IOUtils.copy(is, os)方法将输入流数据复制到输出流,并关闭输入输出流。此数据为临时数据,服务器重启即消失。

   第十一步。删除临时文件。

   第十二步。在map中设置图片的路径。

   第十三步。新建Agents对象,并将map的键值映射到agents中。

   第十四步。调用AgentsService.addImgs(Agents agents)方法进入service层。

   第十五步。重定向到按页查询的Servlet请求。

 

   业务层。

   直接调用AgentsDao.addImags(Agents agents)方法进入dao层。

 

   持久层。

   根据药品id条件更新药品的aimg属性。

 

   至此,后台药品所有功能讲完。

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值