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原理的大体内容,,至少我是这么理解的。欢迎大家批评指正。
- struts原理(手写原理)
- springmvc原理详解(手写springmvc)
- spring 原理手写代码
- Struts原理
- struts原理
- Struts 原理
- Struts原理
- Struts原理
- Struts 原理
- struts原理
- Struts原理
- struts原理
- struts原理
- struts原理
- Struts 原理
- Struts(1)Struts概念和原理
- (二)struts之原理
- Struts原理与实践(1)
- centos7、unbutu14安装rabbitmq
- 自己手写的一个关于中英文切换时间的工具类
- 10 SQL optimization
- DTcms(四)
- 手机软键盘搜索按钮实现点击搜索功能
- struts原理(手写原理)
- Educational Codeforces Round 25 B. Five-In-a-Row
- android 复习和NOde JS 学习篇 模拟登陆,文件上传Demo
- Ubuntu16.04下为pycharm设置快速启动项
- 通过RTMP play分析FLV格式详解
- 编程实现统计某年某月份的天数。
- microsoft server 2014安装配置
- 支持向量机SVM基本理论
- jQuery ajax()使用serialize()提交数据