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

本文详细阐述了如何使用MVC架构,通过抽象工厂+反射模式,实现业务逻辑层与持久化逻辑层之间的弱化依赖。通过配置XML文件来管理类的实例化,便于后期修改而不需改动代码,提高了系统的灵活性和可维护性。

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

内容概要:本文设计了一种基于PLC的全自动洗衣机控制系统内容概要:本文设计了一种,采用三菱FX基于PLC的全自动洗衣机控制系统,采用3U-32MT型PLC作为三菱FX3U核心控制器,替代传统继-32MT电器控制方式,提升了型PLC作为系统的稳定性与自动化核心控制器,替代水平。系统具备传统继电器控制方式高/低水,实现洗衣机工作位选择、柔和过程的自动化控制/标准洗衣模式切换。系统具备高、暂停加衣、低水位选择、手动脱水及和柔和、标准两种蜂鸣提示等功能洗衣模式,支持,通过GX Works2软件编写梯形图程序,实现进洗衣过程中暂停添加水、洗涤、排水衣物,并增加了手动脱水功能和、脱水等工序蜂鸣器提示的自动循环控制功能,提升了使用的,并引入MCGS组便捷性与灵活性态软件实现人机交互界面监控。控制系统通过GX。硬件设计包括 Works2软件进行主电路、PLC接梯形图编程线与关键元,完成了启动、进水器件选型,软件、正反转洗涤部分完成I/O分配、排水、脱、逻辑流程规划水等工序的逻辑及各功能模块梯设计,并实现了大形图编程。循环与小循环的嵌; 适合人群:自动化套控制流程。此外、电气工程及相关,还利用MCGS组态软件构建专业本科学生,具备PL了人机交互C基础知识和梯界面,实现对洗衣机形图编程能力的运行状态的监控与操作。整体设计涵盖了初级工程技术人员。硬件选型、; 使用场景及目标:I/O分配、电路接线、程序逻辑设计及组①掌握PLC在态监控等多个方面家电自动化控制中的应用方法;②学习,体现了PLC在工业自动化控制中的高效全自动洗衣机控制系统的性与可靠性。;软硬件设计流程 适合人群:电气;③实践工程、自动化及相关MCGS组态软件与PLC的专业的本科生、初级通信与联调工程技术人员以及从事;④完成PLC控制系统开发毕业设计或工业的学习者;具备控制类项目开发参考一定PLC基础知识。; 阅读和梯形图建议:建议结合三菱编程能力的人员GX Works2仿真更为适宜。; 使用场景及目标:①应用于环境与MCGS组态平台进行程序高校毕业设计或调试与运行验证课程项目,帮助学生掌握PLC控制系统的设计,重点关注I/O分配逻辑、梯形图与实现方法;②为工业自动化领域互锁机制及循环控制结构的设计中类似家电控制系统的开发提供参考方案;③思路,深入理解PL通过实际案例理解C在实际工程项目PLC在电机中的应用全过程。控制、时间循环、互锁保护、手动干预等方面的应用逻辑。; 阅读建议:建议结合三菱GX Works2编程软件和MCGS组态软件同步实践,重点理解梯形图程序中各环节的时序逻辑与互锁机制,关注I/O分配与硬件接线的对应关系,并尝试在仿真环境中调试程序以加深对全自动洗衣机控制流程的理解。
评论 23
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值