实现Struts2跳转功能

MVC 框架最基础的功能就是跳转,struts2支持注解+xml配置跳转,在这里我设计成xml配置的跳转。

配置跳转需要用到的知识有:反射,xml读取。

反射是实现动态装配的基础,它使我们的程序更具动态性和可扩展性,几乎所有的流行框架都以它为基础实现。xml读取基本都会采用dom4j完成。

实现跳转的过程:xml配置命名空间,Action处理类,请求的action方法和跳转的页面,在form提交请求后,被中心Servlet处理,解析出请求的路径,根据xml配置的各种信息,反射调用目标Action类的处理方法,并且根据xml配置的目标跳转页面进行跳转。

因此提炼出的 核心配置有

1、namcespace:命名空间,不同模块有不同的namespace。

2、name:form请求的名字。

3、method:name对应的Action处理方法名,会被反射调用。

4、 class:Action处理类的全路径,用于在中心Servlet反射生成。

5、 result子标签:Action处理后的跳转页面,跳转方式为forward或redirect。


下面我们就开始实现这个简单的跳转功能:

1、首先建一个web工程(Eclipse),取名Controller

2、接着建一个Filter,取名StrutsFilter,做中心处理器用。(也可以用Servlet,这里我用Filter

3、根目录建control.xml当作跳转配置文件。

<?xml version="1.0" encoding="UTF-8"?>

    //标签名可自定义,这里高仿Struts看着习惯点。
    <struts>
       <package name="user" namespace="/admin">
         <action name="userAction" class="action.UserAction">
          <result name="addUser" >/addUser.jsp</result>
         </action>
       </package>
    </struts>

4、配置web.xml,使其拦截所有action结尾的请求。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	
    <filter>
        <filter-name>struts3</filter-name>
        <filter-class>core.StrutsFilter</filter-class>
    </filter>	
    
    <filter-mapping>
        <filter-name>struts3</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    	
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
  
</web-app>

5 、创建Entity( ActionEntity、PackageEntity、ResultEntity)

package core;

import java.util.List;

public class ActionEntity {
	
	private String name;
	private String classname;
	private List<ResultEntity> result;
	
	public List<ResultEntity> getResult() {
		return result;
	}
	public void setResult(List<ResultEntity> result) {
		this.result = result;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassname() {
		return classname;
	}
	public void setClassname(String classname) {
		this.classname = classname;
	}
}

package core;

import java.util.List;

public class PackageEntity {
	
	private String name;
	private String namespace;
	private List<ActionEntity> action;
	
	public List<ActionEntity> getAction() {
		return action;
	}
	public void setAction(List<ActionEntity> action) {
		this.action = action;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNamespace() {
		return namespace;
	}
	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}
}

package core;

public class ResultEntity {
	private String name;
	private String page;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPage() {
		return page;
	}
	public void setPage(String page) {
		this.page = page;
	}
}

6、创建解析xml的类(ConfigUtils),实现配置文件的解析功能。

package core;

import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 解析配置文件
 * @author Candy
 *
 */
public class ConfigUtils {
	
	//创建封装对象,把从配置文件中读取到的值设置到对象里。(这里假设只有一个package,如果多个换成集合)
	public static PackageEntity packageEntity=new PackageEntity();

	public static void config(){	
        	//创建解析对象
        	SAXReader reader= new SAXReader();
        try {
        	//读取自定的配置文件
	        Document document= reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("control.xml"));
		//得到根元素
		Element root=document.getRootElement();
                //得到根元素下面的package元素
		Element packageElement=root.element("package");
                packageEntity.setName(packageElement.attributeValue("name"));
                packageEntity.setNamespace(packageElement.attributeValue("namespace"));
                
                //得到package里面的所以action元素
                List<Element> listActions=packageElement.elements("action");
            
                //创建一个集合用来存得到的所有的action元素,后面要把这个集合设置到封装的package对象里面。
                List<ActionEntity> action=new ArrayList<ActionEntity>();
                //循环得到每一个action元素,并把得到的action的值设置到封装的action对象里。
                for( Element actionElement :listActions){
            	   ActionEntity actionEntity=new ActionEntity();
            	   actionEntity.setName(actionElement.attributeValue("name"));
            	   actionEntity.setClassname(actionElement.attributeValue("class"));
            	//得到action里面的所有result元素,
            	List<Element> listResult=actionElement.elements("result");
            	
            	//创建一个集合用来存储得到的所以的result元素,后面要把这个集合设置到封装的action对象里面
            	List<ResultEntity> result=new ArrayList<ResultEntity>();
            	//循环得到每一个result元素,并把得到的值设置到封装的result对象里。
            	for(Element resuleElement :listResult){
            		ResultEntity resultEntity=new ResultEntity();
            		resultEntity.setName(resuleElement.attributeValue("name"));
            		resultEntity.setPage(resuleElement.getText());
            		//把创建的所有的并赋值后的result添加的上面定义的集合里面。
            	    result.add(resultEntity);
            	}
            	//这里把上面有数据的result所有集合设置到所有的action封装对象里面。
            	actionEntity.setResult(result);
            	//把包含所有result的所有action添加到上面定义的这个action的集合里
            	action.add(actionEntity);
                }
                //把含有所有数据的action这个集合设置到package这个封装的对象里。
                packageEntity.setAction(action);
                } catch (DocumentException e) {
		        	e.printStackTrace();
	         	}
	  }
}

7、实现StrutsFilter中跳转的核心功能。

package core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
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.HttpServletRequest;

/**
 * 实现基本跳转功能
 * @author Candy
 *
 */
public class StrutsFilter implements Filter{
	@Override
	public void destroy() {
	}
	@Override
	public void doFilter(ServletRequest request0, ServletResponse response0,
			FilterChain chain) throws IOException, ServletException {
	    //得到封装的package对象。
	    PackageEntity pack=ConfigUtils.packageEntity;
	    //得到用户访问的路径。
	    HttpServletRequest request=(HttpServletRequest)request0;
	    String path=request.getServletPath();
	    //拆分得到的路径。
	    String [] pathArr=path.split("/");
	    //namespace的名字。
	    String nameSpace=pathArr[1];
	    //action的名字和方法的一个整体。
	    String action=pathArr[2];
	    //接着查拆分这个整体,得到action名
	    String actionName=action.split("!")[0];
	    //得到方法名
	    String methodName=action.split("!")[1].split("\\.")[0];
	    List<ActionEntity>listAction=pack.getAction();
	    ActionEntity doAction=null;
	    for(ActionEntity ae:listAction){
	    	if(ae.getName().equals(actionName)){
	    		doAction=ae;
	    		break;
	    	}
	    }
	    try {
	    	//反射一个action的类
			Class actionClass=Class.forName(doAction.getClassname());
			//创建一个action的对象。
		    Object actionObject=actionClass.newInstance();
		    //再次得到类
			Class cla=actionObject.getClass();
			//调用用户访问路径里的方法
			Method actionMethod= cla.getDeclaredMethod(methodName);
			//执行方法
			String resultValue=(String)actionMethod.invoke(actionObject,null);
			//得到result的集合。然后查找对应的result返回。
			List<ResultEntity> listResult=doAction.getResult();
			ResultEntity result=null;
			for(ResultEntity re: listResult){
				if(re.getName().equals(resultValue)){
					result=re;
					break;
				}
			}
			//得到跳转的页面
			String page=result.getPage();
			request.getRequestDispatcher(page).forward(request, response0);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	            ConfigUtils.config();	
	}
}

8、到此为止一个简单的跳转功能就实现了。测试代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
     <title>首页</title>
  </head>
 
  <body>
      <a href="<%=path%>/admin/userAction!toAddUser.action">添加用户</a>
  </body>
</html>

package action;

public class UserAction {	
	public String toAddUser(){
	    System.out.println("添加新用户");
		return "addUser";
	}
}

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
        添加用户成功。
  </body>
</html>


你可能感兴趣的:(struts,filter,拦截,解析xml,跳转)