透过DRP进一步认识MVC架构(二)

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

你可能感兴趣的:(DAO,mvc,String,servlet,service,Class)