业务逻辑层依赖持久化逻辑层,为了将这种依赖关系进一步弱化,采用了抽象工厂+反射的模式,把关于Dao层的类配置到xml文件中,然后通过工厂创建对象,后期如果需要修改,只需修改xml文件即可,不用再去修改代码。首先创建一个保存类名称的xml文件beans-config.xml。代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<service-class>
<service id="com.snail.drp.basedata.manager.ItemManager" class="com.snail.drp.basedata.manager.ItemManagerImpl"></service>
<service id="com.snail.drp.flowcard.manager.FlowCardManager" class="com.snail.drp.flowcard.manager.impl.FlowCardManagerImpl"></service>
<service id="com.snail.drp.statreport.manager.StatReportManager" class="com.snail.drp.statreport.manager.impl.StatReportManagerImpl"/>
</service-class>
<dao-class>
<dao id="com.snail.drp.basedata.dao.ItemDao" class="com.snail.drp.basedata.dao.ItemDao4OracleImpl"></dao>
<dao id="com.snail.drp.flowcard.dao.FlowCardDao" class="com.snail.drp.flowcard.dao.impl.FlowCardDaoImpl"></dao>
</dao-class>
</beans>
创建一个抽象工厂,用来创建Dao层的对象,代码如下:
package com.snail.drp.util;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.snail.drp.basedata.dao.ItemDao;
/**
* 工厂抽象
* @author yuanfubiao
*
*/
public class BeanFactory {
private static BeanFactory instance = new BeanFactory();
private final String beansConfigFile = "beans-config.xml";
//保存Service相关对象
private Map serviceMap = new HashMap();
//保存dao相关对象
private Map daoMap = new HashMap();
private Document doc;
private BeanFactory(){
try {
doc = new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
} catch (DocumentException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public static BeanFactory getInstance(){
return instance;
}
/**
* 根据产品编号取得Service系列产品
* @param c
* @return
*/
public synchronized Object getServiceObject(Class c){
//如果存在相关对象实例,返回
if(serviceMap.containsKey(c.getName())){
return serviceMap.get(c.getName());
}
Element beanElt = (Element)doc.selectSingleNode("//service[@id=\"" + c.getName() + "\"]");
String className = beanElt.attributeValue("class");
Object service = null;
try {
service = Class.forName(className).newInstance();
//采用动态代理包装Service
TransactionHandler transactionHandler = new TransactionHandler();
service = transactionHandler.newProxyInstance(service);
//将创建好的对象放到Map中
serviceMap.put(c.getName(), service);
} catch (Exception e) {
throw new RuntimeException();
}
return service;
}
/**
* 根据产品编号取得Dao系列产品
* @param c
* @return
*/
public synchronized Object getDaoObject(Class c){
//如果存在相关对象实例,返回
if(daoMap.containsKey(c.getName())){
return daoMap.get(c.getName());
}
Element beanElt = (Element)doc.selectSingleNode("//dao[@id=\"" + c.getName() + "\"]");
String className = beanElt.attributeValue("class");
Object dao = null;
System.out.print(className);
try {
dao = Class.forName(className).newInstance();
//将创建好的对象放到Map中
daoMap.put(c.getName(), dao);
} catch (Exception e) {
e.printStackTrace();
}
return dao;
}
}
为保持通用性,业务逻辑依旧采用面向接口编程:
package com.snail.drp.flowcard.manager;
import java.util.Date;
import com.snail.drp.flowcard.domain.FlowCard;
import com.snail.drp.util.ApplicationException;
import com.snail.drp.util.PageModel;
/**
* 流向单维护业务层接口
* @author yuanfubiao
*
*/
public interface FlowCardManager {
/**
* 添加流向单
* @param flowCard
* @throws ApplicationException
*/
public void addFlowCard(FlowCard flowCard) throws ApplicationException;
}
实现类代码:
package com.snail.drp.flowcard.manager.impl;
import java.sql.Connection;
import java.util.Date;
import java.util.List;
import com.snail.drp.flowcard.dao.FlowCardDao;
import com.snail.drp.flowcard.domain.FlowCard;
import com.snail.drp.flowcard.manager.FlowCardManager;
import com.snail.drp.util.ApplicationException;
import com.snail.drp.util.BeanFactory;
import com.snail.drp.util.ConnectionManager;
import com.snail.drp.util.DaoException;
import com.snail.drp.util.PageModel;
/**
* 流向单维护服务层实现
* @author yuanfubiao
*
*/
public class FlowCardManagerImpl implements FlowCardManager {
private FlowCardDao flowCardDao;
public FlowCardManagerImpl(){
this.flowCardDao = (FlowCardDao)BeanFactory.getInstance().getDaoObject(FlowCardDao.class);
}
@Override
public void addFlowCard(FlowCard flowCard) throws ApplicationException {
try{
//生成流向单单号
String flowCardVouNo = flowCardDao.generateVouNo();
//添加流向单主信息
flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);
}catch(DaoException e){
throw new ApplicationException("添加流向单失败");
}
}
}
在Controller层,因为很多Servlet中要用到BeanFactory工厂类,因此创建一个专门初始化一些数据的Servlet,在服务器启动时,就创建好BeanFactory,和一些常用的常量。
package com.snail.drp.util.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import com.snail.drp.util.BeanFactory;
import com.snail.drp.util.Constants;
/**
* 负责系统在Server启动时初始化
* @author yuanfubiao
*
*/
public class InitServlet extends HttpServlet {
@Override
public void init() throws ServletException {
//创建缺省工厂
//BeanFactory beanFactory = new DefaultBeanFactory();
//将工厂设置到ServletContext中
//this.getServletContext().setAttribute("beanFactory", beanFactory);
//将抽象工厂放到ServletContext中
BeanFactory beanFactory = BeanFactory.getInstance();
this.getServletContext().setAttribute("beanFactory", beanFactory);
//加入常量
getServletContext().setAttribute("add", Constants.ADD);
getServletContext().setAttribute("showAdd", Constants.SHOW_ADD);
}
}
很多Servlet具有共用的方法,因此Servlet采用面向抽象编程,把Servlet中一些公用的方法抽取出来,代码如下:
package com.snail.drp.util.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.snail.drp.sysmgr.domain.User;
import com.snail.drp.util.BeanFactory;
public class BaseServlet extends HttpServlet {
private String command;
private User user;
private BeanFactory beanFactory;
protected String getCommand(){
return command;
}
protected User getCurrentUser(){
return user;
}
protected BeanFactory getBeanFactory(){
//从servletContext中取得BeanFactory
beanFactory = (BeanFactory)this.getServletContext().getAttribute("beanFactory");
return beanFactory;
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
command = request.getParameter("command");
user = (User)request.getSession().getAttribute("user_info");
super.service(request,response);
}
}
Servlet调用业务逻辑层为保持其灵活性,依旧采用抽象工厂+反射的模式,抽象工厂可以创建不同系列的产品,因此此项目中BeanFactory负责生产Dao层对象和业务逻辑层对象。添加流向单Servlet实现代码,
package com.snail.drp.flowcard.web;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.snail.drp.basedata.domain.AimClient;
import com.snail.drp.basedata.domain.Client;
import com.snail.drp.basedata.domain.FiscalYearPeriod;
import com.snail.drp.basedata.domain.Item;
import com.snail.drp.flowcard.domain.FlowCard;
import com.snail.drp.flowcard.domain.FlowCardDetail;
import com.snail.drp.flowcard.manager.FlowCardManager;
import com.snail.drp.util.ApplicationException;
import com.snail.drp.util.Constants;
import com.snail.drp.util.PageModel;
import com.snail.drp.util.servlet.BaseServlet;
/**
* 流向单维护Servlet
* @author yuanfubiao
*
*/
public class FlowCardServlet extends BaseServlet {
private FlowCardManager flowCardManager;
@Override
public void init() throws ServletException {
flowCardManager = (FlowCardManager)getBeanFactory().getServiceObject(FlowCardManager.class);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(Constants.SHOW_ADD.equals(getCommand())){
showAdd(request,response);
}else if(Constants.ADD.equals(getCommand())){
add(request,response);
}else{
//分页查询
search(request,response);
}
}
/**
* 显示添加页面
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
private void showAdd(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
request.getRequestDispatcher("/flowcard/flow_card_add.jsp").forward(request, response);
}
/**
* 添加
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
private void add(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
//供方分销商代码
String clientId = request.getParameter("clientInnerId");
//需方客户代码
String[] aimIds = request.getParameterValues("aimInnerId");
//物料代码
String[] itemNos = request.getParameterValues("itemNo");
//操作数量
String[] qty = request.getParameterValues("qty");
FlowCard flowCard = new FlowCard();
//操作类型
flowCard.setOptType("A");
//取得会计核算期,正常情况下应该从session中取得
FiscalYearPeriod fiscalYearPeriod = new FiscalYearPeriod();
fiscalYearPeriod.setId(1);
flowCard.setFiscalYearPeriod(fiscalYearPeriod);
//分销商
Client client = new Client();
client.setId(Integer.parseInt(clientId));
flowCard.setClient(client);
//取得录入人
flowCard.setRecorder(getCurrentUser());
//操作日期
flowCard.setOptDate(new Date());
//单据状态
flowCard.setVouSts("N");
List<FlowCardDetail> flowCardDetailList = new ArrayList();
for(int i=0;i<aimIds.length;i++){
FlowCardDetail flowCardDetail = new FlowCardDetail();
//需方客户
AimClient aimClient = new AimClient();
aimClient.setId(Integer.parseInt(aimIds[i]));
flowCardDetail.setAimClient(aimClient);
//物料
Item item = new Item();
item.setItemNo(itemNos[i]);
flowCardDetail.setItem(item);
//操作数量
flowCardDetail.setOptQty(new BigDecimal(qty[i]));
//调整标记
flowCardDetail.setAdjustFlag("N");
flowCardDetailList.add(flowCardDetail);
}
flowCard.setFlowCardDetailList(flowCardDetailList);
//通过工厂取得业务逻辑对象
FlowCardManager flowCardManager = (FlowCardManager)getBeanFactory().getServiceObject(FlowCardManager.class);
try{
flowCardManager.addFlowCard(flowCard);
}catch(Exception e){
throw new ApplicationException("登录超时,请重新登录!");
}
response.sendRedirect(request.getContextPath() + "/servlet/flowcard/FlowCardServlet");
}
}
MVC是当下较流行的开发架构模式,Struts就是基于MVC进一步封装而成,因此吃透MVC是非常有助于后面框架学习的。