• 分步学习Struts(四) 自己写Struts框架


         上次我们已经讲解分析了一下Struts原理,这次我们来自己构建一个简单的Struts框架,通过构建Struts框架来了解Struts是如何实现MVC的。

     

    1、回顾Struts原理分析

    不解释,接上篇博客,链接地址如下:

    Struts学习第二步 之 Struts原理分析

    http://blog.csdn.net/zs15932616453/article/details/8919349

     

    2、解析XML文件

    在上篇博客中,我们已经看出Struts做的就是将MVC中的每一层进行联系,而这些联系其实就是由XML配置文件进行关联的,所以这里我们自己写的Struts框架的第一步就是XML文件的解析。我们使用Struts框架默认的名称struts-config.xml,如下图所示。

    计算机生成了可选文字: ‘公WebRoot卜仑META一INF‘臼WEB一INF今子丐!ib尸今struts一con6g.xmi卜罗欲忠新尸--才index.jsp才Iogin一rror.jsp团loginjuccessj、p。才Ioginjsp

     

    解析xml文件,我们用dom4j解析。步骤如下

    1)拷贝jar

    计算机生成了可选文字: ‘公WebRoot卜公,META一INF‘公,WEB一INF团web·xml

    2)编写代码,代码比较简单,不做多余解释

     

    计算机生成了可选文字: ‘吟strutsTest沙src‘田control,囚Action.java。囚ArtionFo,ardjaVa。囚ActionMappingjava。囚Actionservlet.java。囚ActionFormjava。囚LoginActionForm.java。翻JREsystemLibrary〔dkl·7·0-17]卜氢JZ〔〔1.4Libraries卜翻ReferencedLibrarles‘它,WebRoot

    package control;
    
    import java.io.InputStream;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.io.SAXReader;
    
    public class XmlConfigReader {
    	
    	private static XmlConfigReader instance = new XmlConfigReader();
    	
    	private XmlConfigReader() {		
    	}
    	
    	public static XmlConfigReader getInstance() {
    		return instance;
    	}
    	
    	/**
    	 * 将XML文档转换成为Document对象
    	 * @param filepath XML文档对象路径
    	 * @return 转换之后的Document对象
    	 */
    	public Document XML2Document(String filepath){
    		
    		SAXReader reader = new SAXReader();   
    	    Document document = null;  
    	    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filepath);
    		
    		try {
    			document = reader.read(in);
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    		
    		return document;
    	} 	
    	
    }
    


    注意事项:在Java程序中使用dom4j解析xml文件需要注意路径问题,因为web项目发布之后,有些xml文件是不会发布到项目中的,所以就造成了一些文件无法解析在发布的时候找不到。另外web项目发布之后,一些xml文件的相对位置会发生变化,所以在项目中执行很对的xml文件解析也会出现文件未找到错误。具体内容,我们以后专门进行分析。 

     

    3、分析结构

    上一步我们已经能够将xml文件进行解析,接下来我们分析一下XML文件中各个部分分别对应MVC中的那些部分和各个部分之间如何联系,这一点在上一篇中已经做了相依的解释,这里我们不做多余的解释。 

    MVC对应关系部分

    计算机生成了可选文字: 一}23乙咨51111·吟struts丁est‘沙src币1.甲日口p国Adion.java国Act;onFo,ardjava国ActionMappingjava因Actionservlet.java国LoginAction.java国XmICon6gReader.java属靡尸-.国ActionForm.java,压{LoainActionForm.iavaprivatexlnlConfi仁}泛}/**叫不St己t1CXm二tUrni刀5tdl7〔匕q}OJ土IJ--LC乙一之谧昌。JRESystemLlbra甲-邑JZEE1.4Libraries酬ReferencedLibraries‘公WebRoot卜匕,META一INF卜公WEB一INF阵夏170_1刀乙文档转换成为D酬filepat.二:n转换之后p**/IJb工iCDOCUrnen七)2工J乙孟亡」2222份二彰}}彰〕奔〕类}共}效}共}份:::份}SAXReaderre乏DOCllmentd0CI几put"tream二6勺户O曰2ZC乙葬〕骂〕彩〕券〕秦}共}共二一一工try{O,1qJ3娜二澎〕澎〕券〕朱

     

    各部分联系,参见博客,链接如下:

    Struts学习第一步 之 HelloWord

    http://blog.csdn.net/zs15932616453/article/details/8901418

     

    4、基础类编写。

    了解了各个部分对应关系之后,我们来看一下一些基础类的代码,这些代码与真正的Struts代码基本雷同,所以我们这里不做多余的解释代码如下: 

    Action.java代码如下:

    package control;
     
    importjavax.servlet.ServletRequest;
    importjavax.servlet.ServletResponse;
    importjavax.servlet.http.HttpServletRequest;
    importjavax.servlet.http.HttpServletResponse;
     
    importmodel.ActionForm;
     
    publicclass Action {
     
        public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            ServletRequest request,
            ServletResponse response)
            throws Exception {
     
            try {
                return execute(
                    mapping,
                    form,
                    (HttpServletRequest) request,
                    (HttpServletResponse)response);
     
            } catch (ClassCastException e) {
                return null;
            }
     
        }
       
        public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {
     
            return null;
     
        }
       
    }
     

    LoginAction.java代码如下:

    package control;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import model.ActionForm;
    import model.LoginActionForm;
     
    public class LoginAction extends Action {
    
    	@Override
    	public ActionForward execute(ActionMapping mapping, ActionForm form,
    			HttpServletRequest request, HttpServletResponse response)
    			throws Exception {
    		String name=((LoginActionForm)form).getUserName();
    		String forward="";
    		//业务处理部分,我们仅作简单的判断是否是“hello”
    		if("hello".equals(name)){
    			forward="success";
    		}else{
    			forward="error";	
    		}
    		 
    		return mapping.getActionForwards(forward);
    	}
    	
    }
    

     ActionForward.java代码如下: 

    package control;
    
    public class ActionForward {
    
    	private String name;
    	private String path;
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getPath() {
    		return path;
    	}
    	public void setPath(String path) {
    		this.path = path;
    	}
    	
    }
    

     ActiionMapping.java代码如下:

    package control;
    
    import java.util.HashMap;
    
    public class ActionMapping {
    	
    	private String path;
    	private String type;
    	private String name;
    	private String scope;
    
    	private HashMap<String,ActionForward> actionForwardMap=new HashMap<String,ActionForward>(); 
    
    	public String getPath() {
    		return path;
    	}
    
    	public void setPath(String path) {
    		this.path = path;
    	}
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	public String getScope() {
    		return scope;
    	}
    	
    	public void setScope(String scope) {
    		this.scope = scope;
    	}
    
    	public ActionForward getActionForwards(String ActionForwardName) {		
    		ActionForward actionforward=actionForwardMap.get(ActionForwardName);
    		return actionforward;
    	}
    
    	public void addActionForward(ActionForward actionForward) {
    		actionForwardMap.put(actionForward.getName(), actionForward);
    	}	
    
    }
    

    ActionForm.java代码如下: 

    package model;
     
    public abstract class ActionForm {
     
    }

    LoginActionForm.java代码如下: 

    package model;
    
    public class LoginActionForm extends ActionForm {
    
    	private String userName;
    	
    	public String getUserName() {
    		return userName;
    	}
    
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    }
    

    5、初始化

    了解一些基础类之后,我们接下来重点将一些Strtus框架的核心类ActionServlet。首先我们分析Struts初始化工作,Struts初始化执行工作大致分为几个部分,我们这里只讲我们自己写的Struts都执行哪些工作,真正的Struts框架初始化是比较复杂的,我们等到以后再具体分析这些。

     

    ActionServlet中的init()方法中,我们主要将配置文件中的各个部分读取到Map中,代码如下: 

    package control;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import model.ActionForm;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    
     
    public class ActionServlet extends HttpServlet {
    	
    	private String config;
    	private HashMap<String,ActionMapping> actionMappingMap=new HashMap<String,ActionMapping>();
    	private HashMap<String,String> actionFormMap=new HashMap<String,String>();
    	
    	@Override
    	public void init(){	
    		//初始化配置文件
    		initConfig();
    	}	
    
    	/**
    	 * 将struts-config.xml文件中的各个部分初始化到Map中
    	 * 
    	 */
    	private void initConfig(){	
    		
    		//获取struts-config.xml文件位置,这里我们不错处理,取默认即可
    		config=getServletConfig().getInitParameter("config");
    		 
    		String filePath="../.."+config;		
    		//读取XML文件,存储到document中
    		Document doc=XmlConfigReader.getInstance().XML2Document(filePath); 		
    		//读取配置信息到列表中,
    		List<?> actionFormList=doc.selectNodes("struts-config/form-beans/form-bean");
    		List<?> actionList=doc.selectNodes("struts-config/action-mappings/action"); 
    		List<?> actionForwardList=doc.selectNodes("struts-config/action-mappings/action/forward");
    		
    		//遍历ActionForm列表,将配置信息中的ActionForm信息保存到Map中
    		for(int i=0;i<actionFormList.size();i++){
    			String actionFormName=((Element)actionFormList.get(i)).attributeValue("name");
    			String actionFormType=((Element)actionFormList.get(i)).attributeValue("type");
    			actionFormMap.put(actionFormName, actionFormType);
    		}
    		
    		//遍历ActionMapping列表,将配置信息中的ActionMapping信息保存到Map中
    		for(int i=0;i<actionList.size();i++){
    			String actionName = ((Element)actionList.get(i)).attributeValue("name");
    			String actionType = ((Element)actionList.get(i)).attributeValue("type");
    			String actionPath = ((Element)actionList.get(i)).attributeValue("path");
    			String actionScope = ((Element)actionList.get(i)).attributeValue("scope");
    			ActionMapping actionMapping=new ActionMapping();
    
    			//将配置信息加载到ActionMapping中			
    			actionMapping.setName(actionName);
    			actionMapping.setPath(actionPath);
    			actionMapping.setType(actionType);
    			actionMapping.setScope(actionScope);
    			
    			//遍历ActionForward配置部分,将该部分保存到Action中
    			for(int j=0;j<actionForwardList.size();j++){				
    				ActionForward actionForward=new ActionForward();
    				//将配置的ActionForward信息添加到ActionForwar对象中
    				String actionForwardName=((Element)actionForwardList.get(j)).attributeValue("name");
    				String actionForwardPath=((Element)actionForwardList.get(j)).attributeValue("path");
    				actionForward.setName(actionForwardName);
    				actionForward.setPath(actionForwardPath);
    				//将ActionFormWard对象添加到Action中
    				actionMapping.addActionForward(actionForward);
    			}
    			//将Action对象添加到ActionMapping中
    			actionMappingMap.put(actionMapping.getPath(),actionMapping);
    				
    		}		
    	}	
    	
    }
    

     6、处理客户端请求 

    ActionServlet初始化完成之后,我们就可以接受客户请求了,具体的执行代码如下:

    package control;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import model.ActionForm;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    
     
    public class ActionServlet extends HttpServlet {
    	
    	private String config;
    	private HashMap<String,ActionMapping> actionMappingMap=new HashMap<String,ActionMapping>();
    	private HashMap<String,String> actionFormMap=new HashMap<String,String>();
    		
    	@Override
    	protected void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		process(request, response);
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		process(request, response);
    	}
    	
    	protected void process(HttpServletRequest request, HttpServletResponse response)
    	 		throws IOException, ServletException {
    		try {
    			
    			//取得URL
    			String url=request.getRequestURL().toString();//http://192.168.24.170:8080/StrutsTest/login.do
    			int start=url.lastIndexOf("/");
    			int end=url.lastIndexOf(".");		
    			String actionDo=url.substring(start,end);//  /login
    			
    			
    			//获取指定的ActionMapping
    			ActionMapping actionMapping=(ActionMapping)actionMappingMap.get(actionDo);
    			//实例化ActionForm
    			String actionFormType=actionFormMap.get(actionMapping.getName());
    			ActionForm actionForm=(ActionForm)Class.forName(actionFormType).newInstance();
      
    			//获取所有ActionForm中的方法名
    			Method[] methods=actionForm.getClass().getDeclaredMethods();
    			//遍历所有方法,将调用所有setter方法初始化
    			for(int i=0;i<methods.length;i++){
    				String methodName=methods[i].getName();
    				if(methodName.contains("set")== true){					 				
    					String attributeName=methodName.toLowerCase().charAt(3)+methodName.substring(4,methodName.length());
    					actionForm.getClass().getMethod( methodName,new Class[]{String.class}).invoke(actionForm, new Object[]{request.getParameter(attributeName)});
    				}
    			}
    			
    			//实例化Action
    			Action action = (Action)Class.forName(actionMapping.getType()).newInstance();
    			//获取指定的ActionForward对象
    			ActionForward actionForward=action.execute(actionMapping, actionForm, request, response);
    			//转发到指定的页面
    			request.getRequestDispatcher(actionForward.getPath()).forward(request, response);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}	
    }
    


    整合ActionServlet的初始化和客户端请求之后,我们自己写的Struts框架基本就编写完毕了,当然,这只是一个非常简单的实例,很多地方我们都可以进行一些优化。这里主要为了演示,我们就不做过多的工作了。

     

        本文我们主要演示了一个自己写的Struts框架,实例比较简单,下次我们分析一下本篇文章中的XML文件读取的路径相关问题。

  • 相关阅读:
    组件
    Django
    面向对象
    异常处理
    模块1
    Java中权限设置
    java反射机制
    JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式
    JavaScript提高篇之预解释作用域以及this原理及其应用
    js-引用类型-Array
  • 原文地址:https://www.cnblogs.com/zs234/p/3233355.html
Copyright © 2020-2023  润新知