struts原理(手写原理)

来源:互联网 发布:苹果换铃声软件 编辑:程序博客网 时间:2024/06/06 01:25

首先要说明一点的是,本人最近也是刚刚学习struts框架,接触的不是很深,有一些解释不妥当之处,还望大家能够批评指正……
其实呢,struts最重要的就是控制器,而控制器利用的就是dom4j 的xml解析方式来实现action和jsp的前后台数据交互。手写struts原理首先你要在工程里引入dom4j的jar包,
这里写图片描述
上图就是我在自己的工程里加入的jar包
好了,,准备工作大致就这些了。
现在我们利用一个简单的jsp页面和action的数据交互来说一些这个原理,:
简单的写一个jsp页面来进行数据的传入:
login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">    <title>My JSP 'login.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  </head>  <body>      //简单的form表单,用于提交用户名和密码      //注意这里form表单的action提交的地址:login.action    <form action="login.action" method="post">        username:<input name="username" /><br />        uesrpass:<input name="userpass" /><br />        <input type="submit" value="登录" />    </form>  </body></html>

这样通过form表单就把用户登陆的数据提交到后台的login.action中了
那么现在我就写一下我们后台action中的处理jsp传过来的数据,
login.jsp代码如下:

package com.ruide.action;public class LoginAction {    //声明jsp中提交的数据类型以及变量名,    private String username;    private String userpass;    //提供对应的get和set方法    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getUserpass() {        return userpass;    }    public void setUserpass(String userpass) {        this.userpass = userpass;    }    //进行一次规定 我们规定 所有的action的处理请求的方法    //都叫execute()    //返回值为String 类型    public String execute(){        System.out.println("我的loginaction,我执行了...");        System.out.println("我是execute方法,我的用户名"+username+"我的密码是"+userpass);        return "bb";    }}

在struts框架中,jsp与action之间的交互远远没有表面上那么简单的,它还需要中间还很多的数据操作,这就是我们要提到的重点,struts运行原理
好了,,现在我们要开始进行重中之重的操作了

大家都知道struts框架都有struts.xml配置文件,在我的这个工程呢,,我通过刚才上文中写的action配置了一个struts.xml文件,代码如下:

<?xml version="1.0" encoding="UTF-8"?>//struts.xml的根目录<struts>    //第二级目录,package,struts是通过包来管理action的    <package name="my">        //具体的action类        <action name="login" class="com.ruide.action.LoginAction">            //action中execute方法返回的String类型的字符串结果            //aa bb action中我写的execute方法返回的字符串结果            <result name="aa">success.jsp</result>            <result name="bb" type="redirect">login.jsp</result>        </action>    </package></struts>

下面就是struts框架的核心的东西了, controler类,这个类里面的代码是我们struts框架的核心,重中之重*:*

controler这个类里面利用了dom4j解析来对struts.xml配置文件进行解析,在init方法中利用dom4j解析了struts.xml文件,将struts.xml中所有的标签以及标签属性,标签里面的内容都解析出来,然后根据标签的级别和ActionMessage.java/ActionMapping.java/ResultMessage.java的对应关系将解析出来的信息封装在这几个类中,然后就是dofilter方法,在这里呢,我们用了反射机制(通过类名字找到相应的类),
然后呢通过下面的两行代码创建类对象(不需要new)

Class object=Class.forName(classname);Object obj=object.newInstance();

找到类之后拿到类中的属性:

Field fs[]=object.getDeclaredFields();

然后将类中的得到的属性数组,用增强for循环得到每一个属性的属性名以及属性值,然后得到相应的set方法,然后把得到的属性值封装到创建的obj对象中,

for (Field f:fs) {    String paramname=f.getName();    String paramvalue=request.getParameter(paramname);    System.out.println(paramname+"="+paramvalue);    String methodname="set"+    paramname.substring(0,1).toUpperCase()    +paramname.substring(1);    System.out.println(methodname);    Method m=object.getDeclaredMethod(methodname,String.class);    m.invoke(obj, paramvalue);}

最后呢,找到action中的execute方法执行,最后返回result:

//execute方法执行Method execute=object.getDeclaredMethod("execute");Object objresult=execute.invoke(obj);String result=objresult.toString();System.out.println("要转发的结果为"+result);//处理转发问题...ResultMessage rm=am.getResults().get(result);System.out.println("要转发的类型为");System.out.println(rm.getResulttype());System.out.println("转发的路径为"+rm.getResultpath());if (rm.getResulttype()==null) {//请求转发                                                               request.getRequestDispatcher(rm.getResultpath()).forward(request, response);}else{    response.sendRedirect(rm.getResultpath());}

controler.java代码如下:

package com.ruide.struts;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;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;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;//写了一个实现filter接口的类,public class Controler implements Filter {    //重写destory方法    public void destroy() {    }    //实现init方法    public void init(FilterConfig filterConfig) throws ServletException {        //在init方法中 解析配置文件struts.xml        //一个action 就对应了一个actionmessage        //多个action应该存放到一个hashmap集合中        InputStream in=this.getClass().getClassLoader().getResourceAsStream("struts.xml");        SAXReader reader=new SAXReader();        Document doc=null;        try {            doc=reader.read(in);        } catch (DocumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        Element root=doc.getRootElement();        Element pack=root.element("package");        List<Element> actions=pack.elements("action");        for (Element action:actions) {            String actionname=action.attributeValue("name");            System.out.println(actionname);            String classname=action.attributeValue("class");            System.out.println(classname);            ActionMessage am=new ActionMessage();            am.setClassname(classname);            List<Element> results=action.elements("result");            for (Element result:results) {                String resultname=result.attributeValue("name");                System.out.println(resultname);                String resulttype=result.attributeValue("type");                System.out.println(resulttype);                String resultpath=result.getText();                System.out.println(resultpath);                //type  redirect null dispatcher                ResultMessage rm=new ResultMessage();                rm.setResultpath(resultpath);                rm.setResulttype(resulttype);//null 请求转发 redirect 重定向                am.getResults().put(resultname, rm);            }            ActionMapping.actions.put(actionname, am);        }    }    //实现dofilter方法    public void doFilter(ServletRequest req, ServletResponse resp,            FilterChain chain) throws IOException, ServletException {        //过滤器  过滤所有的后缀名为.action的请求        HttpServletRequest request=(HttpServletRequest) req;        HttpServletResponse response=(HttpServletResponse) resp;        String uri=request.getRequestURI();        uri=uri.substring(uri.lastIndexOf("/")+1);        String actionname=uri.substring(0,uri.indexOf("."));        ActionMessage am=ActionMapping.actions.get(actionname);        String classname=am.getClassname();        //反射得到类对象        try {            Class object=Class.forName(classname);            Object obj=object.newInstance();            //解析到类了            //能不能拿到属性            Field fs[]=object.getDeclaredFields();            for (Field f:fs) {                String paramname=f.getName();                String paramvalue=request.getParameter(paramname);                System.out.println(paramname+"="+paramvalue);                String methodname="set"+paramname.substring(0,1).toUpperCase()+paramname.substring(1);                System.out.println(methodname);                Method m=object.getDeclaredMethod(methodname,String.class);                m.invoke(obj, paramvalue);            }            //execute方法执行            Method execute=object.getDeclaredMethod("execute");            Object objresult=execute.invoke(obj);            String result=objresult.toString();            System.out.println("要转发的结果为"+result);            //处理转发问题...            ResultMessage rm=am.getResults().get(result);            System.out.println("要转发的类型为");            System.out.println(rm.getResulttype());            System.out.println("转发的路径为"+rm.getResultpath());            if (rm.getResulttype()==null) {//请求转发                request.getRequestDispatcher(rm.getResultpath()).forward(request, response);            }else{                response.sendRedirect(rm.getResultpath());            }        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

在controler中提到的几个类,,(ResultMessage.java 、ActionMessage.java、 ActionMapping.java)还没有写,现在补上:

ActionMapping.java代码:

package com.ruide.struts;import java.util.HashMap;import java.util.Map;public class ActionMapping {    //map集合,存放了action名字和ActionMessage的对应关系    public static Map<String, ActionMessage> actions=new HashMap<String, ActionMessage>();}

ActionMessage.java代码:

package com.ruide.struts;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;//action 名字 和类名字 和它的结果路径 要对应起来public class ActionMessage {    //action对应的类的名字    private String classname;    //结果名字 对应着一个ResultMessage    private Map<String,ResultMessage> results=new HashMap<String,ResultMessage>();    public String getClassname() {        return classname;    }    public void setClassname(String classname) {        this.classname = classname;    }    public Map<String, ResultMessage> getResults() {        return results;    }    public void setResults(Map<String, ResultMessage> results) {        this.results = results;    }}

ResultsetMessage.java代码:

package com.ruide.struts;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;//action 名字 和类名字 和它的结果路径 要对应起来public class ActionMessage {    //action对应的类的名字    private String classname;    //结果名字 对应着一个ResultMessage    private Map<String,ResultMessage> results=new HashMap<String,ResultMessage>();    public String getClassname() {        return classname;    }    public void setClassname(String classname) {        this.classname = classname;    }    public Map<String, ResultMessage> getResults() {        return results;    }    public void setResults(Map<String, ResultMessage> results) {        this.results = results;    }}

以上呢,就是struts原理的大体内容,,至少我是这么理解的。欢迎大家批评指正。

原创粉丝点击