struts2自定义框架

自定义框架
  • 自定义框架目录结构

  • 创建framework.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <framework>
        <action name="hello" class="com.eric.action.HelloAction" method="hello">
            <result name="success" type="dispatcher">/index.jsp</result>
            <result name="failed" type="redirect">/index.jsp</result>
        </action>
    </framework>
    • 根据xml文件中定义的节点<action> <result>创建对应的Action Result
  • Action类

    public class Action {
        private String name;
        private String classes;
        private String method = "execute";
        private Map<String, Result> resultMap = new HashMap<String, Result> ();
        public Action() {
            super();
        }
        public Action(String name, String classes, String method) {
            super();
            this.name = name;
            this.classes = classes;
            this.method = method;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getClasses() {
            return classes;
        }
        public void setClasses(String classes) {
            this.classes = classes;
        }
        public String getMethod() {
            return method;
        }
        public void setMethod(String method) {
            this.method = method;
        }
        public Map<String, Result> getResultMap() {
            return resultMap;
        }
        public void setResultMap(Map<String, Result> resultMap) {
            this.resultMap = resultMap;
        }
    }
    • 配置文件中method可以为空,即默认执行execute方法
  • Result类

    public class Result {
        private String name = "success";
        private String type = "dispatcher";
        private String location;
        public Result() {
            super();
        }
        public Result(String location) {
            super();
            this.location = location;
        }
        public Result(String type, String location) {
            super();
            this.type = type;
            this.location = location;
        }
        public Result(String name, String type, String location) {
            super();
            this.name = name;
            this.type = type;
            this.location = location;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public String getLocation() {
            return location;
        }
        public void setLocation(String location) {
            this.location = location;
        }
    }
    • name默认为success
    • type默认为dispatcher
  • 解析xml配置文件

    • 导入dom4j jar包
    • 创建AcrionMapper对象用于解析xml文件
      public class ActionMapper {
          public static Map<String, Action> actionMap = new HashMap<String, Action> ();
          //解析xml配置文件
          public static void parser() throws DocumentException {
              InputStream is = ActionMapper.class.getClassLoader().getResourceAsStream("framework.xml"); 
              Document document = new SAXReader().read(is);
              Element root = document.getRootElement();
              //处理aciton节点
              List<Element> actions = root.elements();
              for(Element element : actions) {
                  Action action = new Action();
                  //获取action的属性值
                  action.setName(element.attributeValue("name"));
                  action.setClasses(element.attributeValue("class"));
                  String method = element.attributeValue("method");
                  if(method != null) {
                      action.setMethod(method);
                  }
                  //处理action中的result
                  List<Element> results = element.elements();
                  for(Element e : results) {
                      Result result = new Result();
                      String resultName = e.attributeValue("name");
                      String resultType = e.attributeValue("type");
                      if(resultName != null) { 
                          result.setName(resultName);
                      }
                      if(resultType != null) {
                          result.setType(resultType);
                      }
                      result.setLocation(e.getStringValue());
                      //将result对象添加到action中
                      action.getResultMap().put(result.getName(), result);    
                  }
                  //将action放入actionmap中
                  actionMap.put(action.getName(), action);
              }
          }
      }
  • 创建核心过滤器

    public class CoreFilter implements Filter{
        @Override
        public void destroy() {
        }
        @Override
        public void init(FilterConfig config) throws ServletException {
            //初始化时解析配置文件
            try {
                ActionMapper.parser();
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void doFilter(ServletRequest rq, ServletResponse rp, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) rq;
            HttpServletResponse resp = (HttpServletResponse) rp;
            //1---将请求映射到action中
            Action targetAction = reqToAction(req);
    //      System.out.println(targetAction.getName());
    //      System.out.println(targetAction.getMethod());
    //      System.out.println(targetAction.getClasses());
            if(targetAction == null) {
                chain.doFilter(rq, rp);
            }
            try {
                //2---创建action对象
                Object proxyAction = createProxyAction(targetAction.getClasses());
                //3---将用户提交的数据设置到action的属性中
                setProperty(req, proxyAction);
                //4---执行action的方法,返回执行结果
                String result = execute(proxyAction, targetAction.getMethod());
                //5---处理action方法的结果
                //重定向用resp,转发用req
                //根据结果获取对应的Result对象,并且作为参数传入
                Result r = targetAction.getResultMap().get(result);
                resultExecute(req, resp, r, proxyAction);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //1---将请求映射到action中
        private Action reqToAction(HttpServletRequest req) {
            String path = req.getRequestURI();
            //uri不正确,只处理action结尾的请求
            if(!path.endsWith(".action")) {
                return null;
            }
            //获得请求的名
            String reqName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
            return ActionMapper.actionMap.get(reqName);
        }
        //2---创建action对象
        private Object createProxyAction(String className) throws Exception {
            Class clzz = Class.forName(className);
            return clzz.newInstance();
        }
        //3---将用户提交的数据设置到action的属性中 --- 简化了很多细节
        private void setProperty(HttpServletRequest req, Object obj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
            //创建Class
            Class clzz = obj.getClass();
            Map map = req.getParameterMap();
            for(Iterator iter = map.keySet().iterator(); iter.hasNext();) {
                Object key = iter.next();
                //根据提交的参数查找Field
                Field field = clzz.getDeclaredField(key.toString());
                if(field == null) {
                    continue;
                }
                field.setAccessible(true);
                //要进行相应的类型转换,此处省略
                field.set(obj, req.getParameter(key.toString()));
                field.setAccessible(false); 
    //          System.out.println(key + "-----" + req.getParameter(key.toString()));
            }
        }
        //4---执行action的方法
        private String execute(Object proxyAction, String method) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            Class clzz = proxyAction.getClass();
            //获取类方法
            Method m = clzz.getDeclaredMethod(method);
            //执行方法
            return (String) m.invoke(proxyAction);
        }
        //5---处理action方法的结果
        private void resultExecute(HttpServletRequest req, HttpServletResponse resp, Result r, Object proxyAction) throws IOException, IllegalArgumentException, IllegalAccessException, ServletException {
            //判断结果类型
            //重定向
            if("redirect".equals(r.getType())) {
                resp.sendRedirect(r.getLocation());
            }
            //转发
            //将action的属性值设置到request的attribute中
            //只能通过Class获取属性 --- 原因:有的属性不是通过前台页面提交过来的
            Class clzz = proxyAction.getClass();
            //fds --- 获取类中所有的属性
            Field[] fds = clzz.getDeclaredFields();
            for(Field fd : fds) {
                //传入属性名,以及属性在该对象中的值
                fd.setAccessible(true);
                req.setAttribute(fd.getName(), fd.get(proxyAction));
                fd.setAccessible(false);
            }
            req.getRequestDispatcher(r.getLocation()).forward(req, resp);
        }
    }
    • 核心过滤器中的关键处理流程
      • 初始化时解析配置文件
        • 调用ActionMapper对象解析xml文件,并将结果存储在actionMap<uri, Action>
      • 将请求映射到action中
        • 获取请求uri,并根据uri在actionMap中查找对应的Action对象
      • 创建action对象
        • 根据Action对象的类型,创建proxyAction对象
      • 将用户提交的数据设置到action的属性中
        • 通过反射机制,获取proxyAction对象的属性域,将req中提交的数据添加到proxyAction的Field中
      • 执行action的方法,返回执行结果
        • 通过反射机制获取proxyAction的方法并且执行
      • 处理action方法的结果
        • 根据返回的执行结果获取对应的Result对象,再根据Result中的type属性进行转发或者重定向
  • 框架执行的总体流程:

    • 解析XML文件,创建Action对象并存储到actionMap

    • 收到请求后,先获取actionMap

    • 根据请求的uri取出actionMap中对应的targetAction

    • 根据targetActionclasses(即<action name="xxx" class="clzz">中的clzz),通过反射机制创建clzz代理类(proxyAction)

      扫描二维码关注公众号,回复: 2247839 查看本文章
    • 根据targetActionmethod属性(即<action name="xxx" class="clzz"> method="method"中的method),通过反射机制获取proxyAction的method方法并且执行

    • 获取执行后的String返回值,根据返回值,在targetActionresultMap中获取对应的Result类

    • 根据Result类的type属性,选择转发或者重定向

猜你喜欢

转载自blog.csdn.net/weixin_40683252/article/details/81113152