zoukankan      html  css  js  c++  java
  • 自定义Struts2实现

    一:struts2运行机制:

      Tomcat一启动,一些信息就已经加载完成,例如StrutsPrepareAndExecuteFilter加载的那些strut.xml以及Action的class类文件

    1)客户端在浏览器中输入一个url地址,例如http://localhost:8080/user!findUser.do
    2)这个url请求通过http协议发送给tomcat。
    3)tomcat根据url找到对应项目里面的web.xml文件。
    4)在web.xml里面会发现有struts2的配置。
    5)然后会找到struts2对应的struts.xml配置文件。
    6)根据url解析struts.xml配置文件就会找到对应的class。
    7)调用完class返回一个字String,根据struts.xml返回到对应的jsp。

    二:struts2运行原理(网络摘抄)

    上图来源于Struts2官方站点,是Struts 2 的整体结构。
    一个请求在Struts2框架中的处理大概分为以下几个步骤:
    1)  客户端初始化一个指向Servlet容器(例如Tomcat)的请求。
    2)  这个请求经过一系列的过滤器(Filter)。
    3)  接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action。
    4)  如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy。
    5)  ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类。
    6)  ActionProxy创建一个ActionInvocation的实例。
    7)  ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
    8)  一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
    Struts2的核心就是拦截器。Struts.xml中所有的package都要extends="struts-default"。同理与所有的Java类都要extends自Object一样。struts-default.xml里面就是要做以上事情。

    三:下面带大家自定义简单的实现一下struts2

    1、创建存放解析struts后的文件,保存里面的name和class以及result结果的Map集合

    package com.s.bean;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class ActionXml {
    	//对应存放的name
    	private String name;
          //对应存放的class
    	private String clazz;
    	//对应存放的那些result,保存ResultXml bean结果
    	private Map results = new HashMap();
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getClazz() {
    		return clazz;
    	}
    	public void setClazz(String clazz) {
    		this.clazz = clazz;
    	}
    	public Map getResults() {
    		return results;
    	}
    	public void setResults(Map results) {
    		this.results = results;
    	}
    }
    


    2、创建存放解析struts后的文件,保存里面的result文件信息

    package com.s.bean;
    
    public class ResultXml {
    	//名称
    	private String name;
    	//值
    	private String value;
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getValue() {
    		return value;
    	}
    	public void setValue(String value) {
    		this.value = value;
    	}
    }
    

    3、创建解析XML的类文件

    package com.s.parse;
    
    import java.io.File;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import com.s.bean.ActionXml;
    import com.s.bean.ResultXml;
    
    public class ParseXml {	
    	private static Map<String,ActionXml> map = new HashMap<String,ActionXml>();
    	public ParseXml(){
    	}
    	public static Map<String,ActionXml> getXML(){
    		SAXReader sax = new SAXReader();
    		Document doc = null;
    		try {
    			doc = sax.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("struts.xml"));
    		} catch (DocumentException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		//得到根目录
    		Element root = doc.getRootElement();
    		//得到所有action配置
    		List list = root.elements();
    		
    		for(Object obj : list){
    			
    			ActionXml ax = new ActionXml();
    			Element a = (Element)obj;
    			
    			ax.setName(a.attributeValue("name"));
    			ax.setClazz(a.attributeValue("class"));
    			
    			//得到所有result
    			List results = a.elements();
    			for(Object obj1 : results){
    				
    				ResultXml rx = new ResultXml();
    				Element r = (Element)obj1;
    				rx.setName(r.attributeValue("name"));
    				rx.setValue(r.getText());
    				ax.getResults().put(rx.getName(), rx.getValue());
    				
    			}
    			//将所有的action的配置读取出来,放入到一个MAP中
    			map.put(ax.getName(), ax);
    		}
    		
    		
    		return map;
    	}
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
           ParseXml.getXML();
    	}
    
    }
    

    4、创建过滤器,tomcat启动后,struts.xml中的文件被解析,并且对应的class文件实体被创建,使用了反射,相当于struts2中的FilterDispatcher

    package com.s.filter;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.s.bean.Action;
    import com.s.bean.ActionXml;
    import com.s.parse.ParseXml;
    import com.sun.org.apache.commons.beanutils.BeanUtils;
    
    public class DispatherFilter  implements Filter {	
        //专门放配置的map
    	private static Map<String ,ActionXml> map;
    	public void doFilter(ServletRequest arg0, ServletResponse arg1,
    			FilterChain arg2) throws IOException, ServletException {
    		// TODO Auto-generated method stub
    		
    		HttpServletRequest request = (HttpServletRequest)arg0;
    		//得到表单请求的名字,比如a
    		String actionName = request.getRequestURI().split("/")[2].split("\\.")[0];
    		//根椐表单请求的名字找到对应的处理类
    		ActionXml ax = map.get(actionName);
    		String clazz = ax.getClazz();
    		String result = "";
    		try {
    			Class cla = Class.forName(clazz);
    			Object obj = cla.newInstance();//根椐clazz产生接收和处理数据的对象
    			
    			//将表单中的数据交给该obj
    			BeanUtils.populate(obj, request.getParameterMap());
    			
    			Action action = (Action)obj;
    			result = action.execute();//执行方法后得到result
    			//根椐result找到对应的要跳转的界面
    			String resultPage = (String)ax.getResults().get(result);
    			//根椐结果页面跳转
    			request.getRequestDispatcher(resultPage).forward(arg0, arg1);
    			
    		} catch (ClassNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (InstantiationException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (InvocationTargetException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    
    	public void init(FilterConfig arg0) throws ServletException {
    		// TODO Auto-generated method stub
    		map = ParseXml.getXML();//读取配置
    	}
    
    
    }
    

    4、定义一个Action的接口类,里面只有一个execute方法

    package com.s.bean;
    
    public interface Action {
    	
    	public String execute();
    
    }
    

    这样,一个小型的框架就完成了,它里面包含Tomcat启动后对struts.xml文件的解析,以及Action类的实体化,这样我们只要定义我们的action实现类和加入我们的struts.xml就可以灵活驾驭这个框架了。

    5、定义struts.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <struts>
      <action name="a" class="com.s.bean.Users">
            <result name='success'>/success.jsp</result>        
              <result name='fail'>/fail.jsp</result>  
               <result name='ok'>/ok.jsp</result>
      </action>  
    </struts>    
    

    6、定义我们的Action的实现类

    package com.s.bean;
    
    import java.io.Serializable;
    
    public class Users implements Serializable,Action{
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = -4293478837686410970L;
    	private int uid;
    	private String uname;
    	private String upwd;
    	public int getUid() {
    		return uid;
    	}
    	public void setUid(int uid) {
    		this.uid = uid;
    	}
    	public String getUname() {
    		return uname;
    	}
    	public void setUname(String uname) {
    		this.uname = uname;
    	}
    	public String getUpwd() {
    		return upwd;
    	}
    	public void setUpwd(String upwd) {
    		this.upwd = upwd;
    	}
    	//处理数据的方法
    	public String execute(){
    		//在这里操作数据库
    		if(uname.equals("admin")){
    		  return "fail";
    		}else{
    			return "success";
    		}
    		
    	}
    }
    

    7、测试页面,或者使用超链接进行测试:http://localhost:8080/a.do?uname=aaa&upwd=bbb

       <form action="a.do" method="post">
          username:<input type="text" name="uname"/><br>
          password:<input type="text" name="upwd"/><br>
          <input type="submit" value="提交"/>
        </form>

    解析:

    Tomcat已启动,DispatherFilter中的init方法得到执行,解析struts.xml文件,并把相应的信息保存在全局变量的map中

    当用户通过超链接的方式访问http://localhost:8080/a.do?uname=aaa&upwd=bbb,转入到DispatherFilter,通过DispatherFilter解析超链接request.getRequestURI().split("/")[2].split("\\.")[0];,得到action中的name名称,然后通过parseXML类得到相对应的class类,然后利用反射机制创建它的实体,系统默认执行里面的execute方法,得到相应的字符串信息,根据返回的字符串信息,通过解析xml找到相应的结果页面,然后通过request.getRequestDispatcher(resultPage).forward(arg0, arg1);跳转到相应的页面,得到相应的结果

    结合struts2原理,我们不然发现struts2中的FilterDispatcher相当与我们自定义的DispatherFilter,里面的ActionMapper就是我们自己定义的全局变量map,至于struts2中的ActionProxy,以及Configuration Manager,ActionInvocation and (Intercepter)我们这里就没有涉及了,用户可以自己依次去实现,这里只是简单的实现了一下struts2的原理,仅供学习参考!

    源代码下载:http://download.csdn.net/detail/harderxin/5229826

  • 相关阅读:
    1373:鱼塘钓鱼(fishing)
    1261:【例9.5】城市交通路网
    1259:【例9.3】求最长不下降序列
    1260:【例9.4】拦截导弹(Noip1999)
    1258:【例9.2】数字金字塔
    1261:【例9.5】城市交通路网
    1260:【例9.4】拦截导弹(Noip1999)
    1259:【例9.3】求最长不下降序列
    1257:Knight Moves
    [HAOI2008]硬币购物(动态规划、容斥、搜索)
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3006145.html
Copyright © 2011-2022 走看看