028-86922220

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

深入理解struts的运行机制


title: 深入理解struts的运行机制
date: 2016-10-26 20:02
tags: java
categories: 编程

成都创新互联公司2013年至今,是专业互联网技术服务公司,拥有项目成都做网站、网站设计、外贸营销网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元湛河做网站,已为上家服务,为湛河各地企业和个人服务,联系电话:028-86922220

permalink: zxh

个人剖析,不喜勿喷

扫码关注公众号,不定期更新干活

深入理解struts的运行机制这里写图片描述

在此申明本博文并非原创,原文:http://blog.csdn.net/lenotang/article/details/3336623,本文章是在此文章基础上进行优化。也谈不上优化,只是加上了点自己的想法

jar包准备

新建项目

流程梳理


如何将我们写的struts.xml文件在程序中启动呢?

新建filter(FilterDispatcher)

}

```
// 获得xml配置文件
        String webRootPath = getClass().getClassLoader()
                .getResource("struts.xml").getPath();
package org.zxh.util;

import java.util.HashMap;
import java.util.Map;

/**
 * 将action属性封装成类
 * @author 87077
 *
 */
public class ActionConfig {

    //action 给别人调用的名字
    private String name;
    //action对应程序中的action类
    private String clazzName;
    //action中的方法
    private String method;
    //返回结果不知一条 所以用Map
    private Map resultMap = new HashMap();

    public ActionConfig(){

    }

    public ActionConfig(String name , String clazzName , String method , Map resultMap){
        this.name=name;
        this.clazzName=clazzName;
        this.method=method;
        this.resultMap=resultMap;
    }

    public String getName() {
        return name;
    }

    public String getClazzName() {
        return clazzName;
    }

    public String getMethod() {
        return method;
    }

    public Map getResultMap() {
        return resultMap;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setClazzName(String clazzName) {
        this.clazzName = clazzName;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public void setResultMap(Map resultMap) {
        this.resultMap = resultMap;
    }

}
package org.zxh.util;

import java.io.File;
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;

/**
 * 采用dom4j解析xml配置文件
 * 
 * @author 87077
 * 
 */
public class ConfigUtil {

    /**
     * @param fileName
     *            待解析的文件
     * @param map
     *            存放解析的数据
     */
    public static void parseConfigFile(String fileName,
            Map map) {
        SAXReader reader = new SAXReader();
        try {
            Document doc = reader.read(new File("D:\\zxh\\soft\\apache-tomcat-7.0.70\\apache-tomcat-7.0.70\\webapps\\MyStruts\\WEB-INF\\classes\\struts.xml"));
            Element root = doc.getRootElement();
            List list = root.selectNodes("package/action");
            for (Element element : list) {
                // 封装成ActionConfig对象,保存在map中
                ActionConfig config = new ActionConfig();
                // 获取action中的值
                String name = element.attributeValue("name");
                String clazzName = element.attributeValue("class");
                String method = element.attributeValue("method");
                // 将值传入javabean中
                config.setName(name);
                config.setClazzName(clazzName);
                // 如果没有设置执行method 执行默认的
                if (method == null || "".equals(method)) {
                    method = "execute";
                }
                config.setMethod(method);
                // 继续向下获取action中的返回方法
                List resultList = element.selectNodes("result");
                for (Element resultElement : resultList) {
                    String resultName = resultElement.attributeValue("name");
                    String urlPath = resultElement.getTextTrim();
                    if (resultName == null || "".equals(resultName)) {
                        resultName = "success";
                    }
                    config.getResultMap().put(resultName, urlPath);
                }
                map.put(name, config);
            }
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
@Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub 过滤器的初始化过程
        // 获得xml配置文件
        String webRootPath = getClass().getClassLoader()
                .getResource("struts.xml").getPath();
        // 将xml配置文件解析装在到map中
        ConfigUtil.parseConfigFile(webRootPath, map);
    }

过滤器的执行

public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2)

doFilter()方法类似于Servlet接口的service()方法。当客户端请求目标资源的时候,容器就会调用与这个目标资源相关联的过滤器的 doFilter()方法。其中参数 request, response 为 web 容器或 Filter 链的上一个 Filter 传递过来的请求和相应对象;参数 chain 为代表当前 Filter 链的对象,在特定的操作完成后,可以调用 FilterChain 对象的 chain.doFilter(request,response)方法将请求交付给 Filter 链中的下一个 Filter 或者目标 Servlet 程序去处理,也可以直接向客户端返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及 HttpServletResponse的sendRedirect()方法将请求转向到其他资源。这个方法的请求和响应参数的类型是 ServletRequest和ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。

//针对http请求,将请求和响应的类型还原为HTTP类型
        HttpServletRequest request = (HttpServletRequest) arg0;
        HttpServletResponse response = (HttpServletResponse) arg1;
        //设置请求和响应的编码问题
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
//获取请求路径
String url = request.getServletPath();
//请求地址过滤,如果不是以.action结尾的
        if(!url.endsWith(".action")){
            //不是.action的放行
            arg2.doFilter(request, response);
            return ;
        }
//解析request路径
        int  start = url.indexOf("/");
        int end = url.lastIndexOf(".");
        String path=url.substring(start+1,end);
        //通过path去匹配到对应的ActionConfig类。在这里已经解析到了所有的action的信息
        ActionConfig config = map.get(path);
        //匹配不成功就返回找不到页面错误信息
        if(config==null){
            response.setStatus(response.SC_NOT_FOUND);
            return ;
        }
//通过ActionConfig获取完成的类名字
        String clazzName=config.getClazzName();
        //实例化Action对象,不存在的话就提示错误信息 
        Object action = getAction(clazzName);
        if(action==null){
            //说明这个action是错误的,在配置文件中没有占到对应的action类
            response.setStatus(response.SC_NOT_FOUND);
            return ;
        }

request参数获取并赋值给action

public static void requestToAction(HttpServletRequest request , Object action )
Class clazzAction = action.getClass();
        //获取aciton中所有属性,从前台获取的值很多,只有action属性中有的才会进行反射赋值
        Field[] fields = action.getClass().getDeclaredFields();
//获取请求中的名字属性值
        Enumeration names=request.getParameterNames();
String name=names.nextElement();
            boolean flag=false;
            //需要判断action属性中没有的而请求中有的我们不需要进行反射处理
            for (Field field : fields) {
                if(name.equals(field.getName())){
                    flag=true;
                }
            }
            if(!flag){
                return;
            }
            String[] value=request.getParameterValues(name);
Class fieldType=(Class) clazzAction.getDeclaredField(name).getType();
  • 获取action的改name字段属性的set方法

//通过反射调用该属性的set方法
                    String setName="set"+name.substring(0,1).toUpperCase()+name.substring(1);
                    Method method=clazzAction.getMethod(setName, new Class[]{fieldType});
  • 下面我们就需要将获取的value按类型

private static Object[] transfer(Class fieldType , String[] value){
        Object[] os = null;
        //fieldType 是[]这种类型的,需要将[]去掉
        String type=fieldType.getSimpleName().replace("[]", "");
        if("String".equals(type)){
            os=value;
        }else if("int".equals(type)||"Integer".equals(type)){
            os = new Integer[value.length];
            for (int i = 0; i < os.length; i++) {
                os[i] = Integer.parseInt(value[i]);
            }
        }else if("float".equals(type)||"Float".equals(type)){
            os=new Float[value.length];
            for (int i = 0; i < os.length; i++) {
                os[i]=Float.parseFloat(value[i]);
            }
        }else if("double".equals(type)||"Double".equals(type)){
            os=new Double[value.length];
            for (int i = 0; i < os.length; i++) {
                os[i]=Double.parseDouble(value[i]);
            }
        }
        return os;
    }
  • 获取object数据之后就是讲这个object数据通过反射付给action对应的属性

//判断是否是数组属性
                    if(fieldType.isArray()){
                        method.invoke(action, new Object[]{object});
                    }else {
                        method.invoke(action, new Object[]{object[0]});
                    }

这说一下 method.invoke是将action类中method方法这个方法需要的参数就是object详解

  • 有了这个方法我们在回到Filter就可以了

//前置拦截,获取request里面的参数,调用action的set方法给属性设置值
        BeanUtil.requestToAction(request, action);
  • 属性赋值完成就开始执行action中的method了

private String executeAction(ActionConfig config, Object action) {
        String method = config.getMethod();
        String result = null;
        try {
            Method callMethod = action.getClass().getMethod(method,String.class);
            result = (String) callMethod.invoke(action, new Object[] {});
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return config.getResultMap().get(result);
    }
  • 到这里你已经获取了配置文件中前台映射后应该的result了,那么就简单了,直接重定向就可以了,到这里就实现了struts的前后台交互。

request.getRequestDispatcher(result).forward(request, response);

  • 下面就在前台jsp中form表单将数据传递给我们的login  action看看会不会去执行指定的方法

详解
  • 有了这个方法我们在回到Filter就可以了

//前置拦截,获取request里面的参数,调用action的set方法给属性设置值
        BeanUtil.requestToAction(request, action);
  • 属性赋值完成就开始执行action中的method了

private String executeAction(ActionConfig config, Object action) {
        String method = config.getMethod();
        String result = null;
        try {
            Method callMethod = action.getClass().getMethod(method,String.class);
            result = (String) callMethod.invoke(action, new Object[] {});
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return config.getResultMap().get(result);
    }
  • 到这里你已经获取了配置文件中前台映射后应该的result了,那么就简单了,直接重定向就可以了,到这里就实现了struts的前后台交互。

request.getRequestDispatcher(result).forward(request, response);

上诉原理的×××

扫码关注公众号,不定期更新干活

深入理解struts的运行机制这里写图片描述
分享文章:深入理解struts的运行机制
标题链接:http://www.tsicrk.com/article/psjisg.html
  • 网站建设专属方案

  • 网站定制化设计

  • 7X24小时服务

  • N对管家服务

让你的专属顾问为你服务

3.7156s