struts2工作原理

首先,我们知道想要通过链接跳转到一个页面执行内容转发到指定页面有两种方式:

1、使用servlet,然后使用request对象或response对象进行跳转

2、使用过滤器拦截在doFilter中使用request或者response进行跳转

一个Filter可以处理多个问题,而且只需要配置一次,我们决定使用过滤器实现。

准备工作:

test.jsp:

 <body>
    入门的路径:<br/>
    <a href="${pageContext.request.contextPath }/primer/userAction.action">userWorld</a><br/>
    
    <br/>
    <a href="${pageContext.request.contextPath }/helloWorld/helloWorldAction.action">helloWorld</a><br/>
  </body>

Action接口:

public interface Action {
    
    public String execute();

}

实现Action:

public class UserAction implements Action {

    public String execute() {
        System.out.println("UserAction ****** execute()");
        return "success";
    }

}
public class HelloWorldAction implements Action {

    public String execute() {
        System.out.println("HelloWorldAction ****** execute()");
        return "success";
    }

}

需求1:

拦截所有请求,执行UserAction的execute()方法,跳转到success.jsp页面

package cn.itcast.action;

import java.io.IOException;
import java.util.HashMap;
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Struts2Filter implements Filter {public void init(FilterConfig config) throws ServletException {
       
    }
    
    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //强转
        HttpServletRequest req=(HttpServletRequest) request;
        HttpServletResponse resp=(HttpServletResponse) response;
               
        UserAction  action = new UserAction();
        action.execute();
                
        req.getRequestDispatcher("/success.jsp").forward(req, resp);
           
        }
          
    }
}

结果:

将过滤器配置在web.xml中,过滤为/*

问题1:进入不了test.jsp,每次都直接跳转到success.jsp

解决方式:

加入条件判断:

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //强转
        HttpServletRequest req=(HttpServletRequest) request;
        HttpServletResponse resp=(HttpServletResponse) response;
        
        String path=req.getServletPath();
        System.out.println("path = "+path);
        if(path.equals("/test.jsp")){
            chain.doFilter(req,resp);
        }else{
       UserAction  action = new UserAction();
          action.execute();
                
          req.getRequestDispatcher("/success.jsp").forward(req, resp);
     } 
}

问题2:

发现每次进入无论点击哪个链接得到的都是UserAction的执行,不符合我们要求:

解决方案:

使用多态,调用父类execute();子类对象使用反射实例化

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //强转
        HttpServletRequest req=(HttpServletRequest) request;
        HttpServletResponse resp=(HttpServletResponse) response;
        
        String path=req.getServletPath();
        System.out.println("path = "+path);
        if(path.equals("/test.jsp")){
            chain.doFilter(req,resp);
        }else{
            try {
                Action action;
                action = (Action) Class.forName("cn.itcast.action.UserAction").newInstance();
                action.execute();
                
                req.getRequestDispatcher("/success.jsp").forward(req, resp);
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
        
    
        
    }

问题3:

class.forName不能定死,我们需要根据path得到对应的路径,然后完成对应的放射,执行响应代码。

解决方案:

使用成员变量map类型装载键值对,将路径作为键,将class文件对应路径作为值,使用get(Object)获取想要的源路径以生成对象。

public class Struts2Filter implements Filter {

    Map<String,String> map=new HashMap<String,String>();
    
    public void init(FilterConfig config) throws ServletException {
        map.put("/primer/userAction.action", "cn.itcast.action.UserAction");
        map.put("/helloWorld/helloWorldAction.action", "cn.itcast.action.HelloWorldAction");
        
    }
    
    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //强转
        HttpServletRequest req=(HttpServletRequest) request;
        HttpServletResponse resp=(HttpServletResponse) response;
        
        String path=req.getServletPath();
        System.out.println("path = "+path);
        if(path.equals("/test.jsp")){
            chain.doFilter(req,resp);
        }else{
            try {
                Action action;
                action = (Action) Class.forName(map.get(path)).newInstance();
                action.execute();
                
                req.getRequestDispatcher("/success.jsp").forward(req, resp);
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
        
    
        
    }

    

}

问题4:

我们每一个路径增加都要改写过滤器,而我们的框架是jar文件,不能轻易改写,怎么达到动态装载map中的键值对的效果呢?

分析:

在一个工程中,xml文件时不需要编译成为.class文件的,所以,我们应该学会在过滤器中取读指定的xml的配置文件,然后自动注入map的兼职对中,完成一一对应。

一个xml例子:

<struts>
    <package namespace="/primer">
        <action name="userAction" class="cn.itcast.action.UserAction">
            <result name="success">/success.jsp</result>
        </action>
    </package>
    
    <package namespace="/helloWorld">
        <action name="helloworldAction" class="cn.itcast.action.HelloWorldAction">
            <result name="success">/success.jsp</result>
        </action>
    </package>
</struts>

剩下的就暂时不深入了,关于解析xml,返回值的使用等等,有时间自己探索吧!

原文地址:https://www.cnblogs.com/aigeileshei/p/5884517.html