程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> 自定義Struts2實現

自定義Struts2實現

編輯:關於JSP

一:struts2運行機制:

  Tomcat一啟動,一些信息就已經加載完成,例如StrutsPrepareAndExecuteFilter加載的那些strut.xml以及Action的class類文件

1)客戶端在浏覽器中輸入一個url地址
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集合

[java]
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; 
    } 

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文件信息

[java]
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; 
    } 

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的類文件


[java]
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(); 
    } 
 

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

[java]
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();//讀取配置  
    } 
 
 

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方法

[java]
package com.s.bean; 
 
public interface Action { 
     
    public String execute(); 
 

package com.s.bean;

public interface Action {
 
 public String execute();

}
這樣,一個小型的框架就完成了,它裡面包含Tomcat啟動後對struts.xml文件的解析,以及Action類的實體化,這樣我們只要定義我們的action實現類和加入我們的struts.xml就可以靈活駕馭這個框架了。

5、定義struts.xml

[html]
<?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>     

<?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的實現類


[java]
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"; 
        } 
         
    } 

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、測試頁面,或者使用超鏈接進行測試


[plain]
<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> 

   <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中

 轉入到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的原理,僅供學習參考!

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved