业务逻辑层依赖持久化逻辑层,为了将这种依赖关系进一步弱化,采用了抽象工厂+反射的模式,把关于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是非常有助于后面框架学习的。