这次在struts2的源码中花了不少的时间。其中收获了不少,源码的功能实现我想如果分解开来人人都能写,关键是他们之间的层次,封装,和接口的应用,这次我就称之为框架的架构吧,虽然我不清楚这个名称是不是符合。struts2我不太会用,只是了解其中的一小部分机制,所以这里我只仿写了配置文件的读取和请求发送时,框架中的处理。关于其他的知识点暂时放着,之后零零碎碎记录
1:配置文件 note:package只有namespace,如果extends加上的话后面需要递归获取父包信息,所以第一次写尽量简单,后面不断完善。
<?xml version="1.0" encoding="UTF-8"?>
<struts>
<package namespace="/center">
<action name="skip" class="web.prim.UltimateServlet" method="test">
<result name="success" type="dispatcher">index.jsp</result>
<result name="fail" type="dispatcher">index.jsp</result>
</action>
</package>
<package namespace="/center1">
<action name="skip_execute" class="web.prim.UltimateServlet">
<result type="dispatcher">
<param name="success">index.jsp</param>
<param name="fail">fail.jsp</param>
</result>
</action>
</package>
</struts>
2:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>dispatcher</filter-name>
<filter-class>com.filter.Struts2FileDispacher</filter-class>
</filter>
<filter-mapping>
<filter-name>dispatcher</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
注意到上边有一个filter的过滤器,主要是拦截一切客户端的请求。接下啦我就从这个类展开。
Struts2FileDispacher 过滤器类
package com.filter;
import java.io.IOException;
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 com.dispatcher.Dispatcher;
import com.mapper.ActionMapping;
public class Struts2FileDispacher implements Filter{
private Dispatcher dispatcher;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) resp;
dispatcher.saveRequestAndResponse(request,response);
ActionMapping actionMapping = dispatcher.getActionMapping(request);
dispatcher.ActionService(actionMapping);
chain.doFilter(req, resp);
}
public void init(FilterConfig arg0) throws ServletException {
dispatcher = new Dispatcher();
dispatcher.init();
}
}
请看 init这个方法,里边初始化了Dispatcher对象,这个对象高度封装,什么是高度封装呢?就是在它的上一层(该拦截器类)想要什么,想实现什么,这个对象都能够提供,它就像是一个架构师,将它下面的层次的类或者方法组装成某个功能方法。现在请看init()方法的实现:
Dispatcher.init()
private static Map<String,Provider> providers = new HashMap<String,Provider>();
/** this method use to initialize the configuration file*/
public void init(){
//use an empty method instead of the special implementation
//so that we can keep a clear head ,rapid development
init_XMLContextProvider();
}
/** here we can concrete implement the empty method*/
public void init_XMLContextProvider(){
Provider provider = new XMLContextProvider().call();
providers.put("xmlContextProvider",provider);
}
这里我只初始化了struts2.xml的文件。所以只创建了一个实现类, Provider这是一个接口,统一提供了一个函数 call()。从这里我体会到了接口的一个好处。博主在晚上灌了一瓶啤酒,晕乎乎的,状态来了后,就可以写整体的框架,什么细节都不想,只按照伪代码,按照逻辑一层层下去。这里如果没有接口,我不得不考虑到底该创建同一种类型类那个具体实现类。而且,如果 这个实现类实现不知道,等待用户的编写,那么在框架中有怎么接收这个类呢?
下面是XMLContextProvider类,这里只是先贴出来,初始化配置文件只是创建这个对象而已。
package com.provide;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
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;
import com.strust2.domain.ActionConfig;
import com.strust2.domain.PackageConfig;
import com.strust2.domain.ResultConfig;
import com.util.StrutsUtil;
/**
* store the user fill out information
* at the struts.xml
* @author Z.B.S.Y
*
*/
public class XMLContextProvider implements Provider{
// read package label informations and
// store in the variable of capsulation packageConfig class
private static List<PackageConfig> packageConfigs;
// provide the special configuration file' path
private String filePath;
// the Document is dom4j capsulation class
private Document doc;
public XMLContextProvider(){
}
//initialize the filePath global variable
public XMLContextProvider(String filePath){
this(filePath,null);
}
public XMLContextProvider(Document doc){
this(null,doc);
}
public XMLContextProvider(String filePath,Document doc){
this.filePath = filePath;
this.doc = doc;
}
public XMLContextProvider call(){
packageConfigs = getPackageConfiguration();
return this;
}
/*
* when we make sure that the variable of doc
* is not null,we do the following things like below
*/
public List<PackageConfig> getPackageConfiguration(){
List<PackageConfig> packageConfs = new ArrayList<PackageConfig>();
//here only has one doc; but struts2 has more than
//one documents,if that is the case we need to loop operation
if(filePath == null){
filePath = "struts.xml";
}
doc = getDocument(filePath);
//get root Element here
Element root = doc.getRootElement();
//if the package Element has a lot of childElement
//we use the way which I has mentioned
Iterator<Element> ite = root.elementIterator("package");
while(ite.hasNext()){
Element packageEle = ite.next();
PackageConfig packageConf = loadPackage(packageEle);
packageConfs.add(packageConf);
}
return packageConfs;
}
//when we only get filePath we should obtain the Document instance
public Document getDocument(String fileName){
//if the doc is empty we should create a new instance
if(doc == null){
//it's a bit of trouble to create new instance we need
//filePath and capsulation class of dom4j. here we can
//provide a method which has no code to achieve
conversionFilePathToDocument(fileName);
}
//otherwise we as long as return doc of class attribute variable
return doc;
}
//we can achieve code here through the filePath.
//Don't you think the use of this method of coding is very convenient?
private void conversionFilePathToDocument(String fileName){
//call the Utility class to get the real configuration path
String filePath = StrutsUtil.getConfigurationPath(fileName);
try {
SAXReader saxReader = new SAXReader();
doc = saxReader.read(new File(filePath));
} catch (DocumentException e) {
String error = "when read the configuration path "+filePath +
"appear this error";
System.out.println(error);
e.printStackTrace();
}
}
// wonderful! don't you think so ? let's finish the method
private PackageConfig loadPackage(Element packageEle){
//create PackageConfig instance at here
PackageConfig packageConfig = new PackageConfig();
//create the List<ActionConfig> of Collection at here
List<ActionConfig> actionConfigs = new ArrayList<ActionConfig>();
// let'me think,we should get action label information here
// through the loop to get all the action label
List<Element> actionEles = packageEle.elements("action");
for(int i = 0; i < actionEles.size(); i++){
Element actionEle = actionEles.get(i);
ActionConfig actionConfig = getActionConfig(actionEle);
actionConfigs.add(actionConfig);
}
//store the collection into the variable of PackageConfig
//wait! we have almost forgotten the package variable
//we get the action variable here
//let's ignore other attributes,to perfect them in the future
String namespace = packageEle.attributeValue("namespace");
//ok! we capsulation all the information in the actionConf
packageConfig.setNamespace(namespace);
packageConfig.setActionConfs(actionConfigs);
return packageConfig;
}
private ActionConfig getActionConfig(Element actionEle){
//get the action's attribute here
String name = actionEle.attributeValue("name");
String clazz = actionEle.attributeValue("class");
String method = actionEle.attributeValue("method");
//there is no method we use the default method the struts2 provide
if(method == null){
method = "execute";
}
//create a ActionConfig instance at here
ActionConfig actionConf = new ActionConfig();
//Each ActionConfig has result labels so create ActionConfig
//instance and obtain the resultConfg at here
List<ResultConfig> resultConfs = getResultConfig(actionEle);
//store the all the information in this ActionConfig variable
actionConf.setClazz(clazz);
actionConf.setMethod(method);
actionConf.setName(name);
actionConf.setResultConfigs(resultConfs);
return actionConf;
}
/** this function to get the resultConfig */
private List<ResultConfig> getResultConfig(Element actionEle){
//here exist two ways to read the result Element
//like <result name="" type="">xxx.jsp</result>
//<result type=""><param name="">content</param></result>
List<ResultConfig> resultConfs = new ArrayList<ResultConfig>();
List<Element> resultEles = actionEle.elements("result");
for(int i = 0; i < resultEles.size(); i++){
Element resultEle = resultEles.get(i);
ResultConfig resultConfig = new ResultConfig();
//get the result label attribute of type
String type = resultEle.attributeValue("type");
Map<String,String> params = loadParams(resultEle);
resultConfig.setParams(params);
resultConfig.setType(type);
resultConfs.add(resultConfig);
}
return resultConfs;
}
//get the result collection by this method
private Map<String,String> loadParams(Element resultEle){
//let's finish the last work to get the result values
Map<String,String> params = new HashMap<String,String>();
List<Element> childsParams = resultEle.elements("param");
if(childsParams != null){
for(int i = 0; i < childsParams.size(); i++){
Element param = childsParams.get(i);
String name = param.attributeValue("name");
String content = param.getText();
params.put(name, content);
}
}
if(params.size() == 0){
//in this case that the result Element has no child Element of param
String name = resultEle.attributeValue("name");
String content = resultEle.getText();
params.put(name, content);
}
return params;
}
}
接下去请看doFilter方法:
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse) resp;
dispatcher.saveRequestAndResponse(request,response);
ActionMapping actionMapping = dispatcher.getActionMapping(request);
dispatcher.ActionService(actionMapping);
chain.doFilter(req, resp);
}
上边的saveRequestAndResponse(request,response)方法的作用:在<result type="dispatcher" >这里需要实现dispatcher所指的对象,这个类需要用request.getRequestDispatcher(path).forward(req,resp)需要这两个变量
dispatcher.getActionMapping(request)
/** find out the action which match the request special path**/
public ActionMapping getActionMapping(HttpServletRequest req){
// here use the ActionMapper to get the action match the request' path.
parsePathAndReturn(req);
ActionMapping actionMapping = new ActionMapping();
actionMapping.mapping();
return actionMapping;
}
/** parse the request path **/
public void parsePathAndReturn(HttpServletRequest req){
String path = req.getRequestURI();
// path will be parsed into this form like objectname + namespace + actionname
// http://localhost:8080/namespace/logon.action
//get the class which action point to and the method defined in the class
//which derive action
String name = path.substring(path.lastIndexOf("/")+1);
String namespace = path.substring(0,path.lastIndexOf("/"));
//if not execute blew step,will contain the objectname
namespace = namespace.substring(namespace.lastIndexOf("/"));
name = removeSuffix(name);
ActionStore.setNamespace(namespace);
ActionStore.setName(name);
}
/** if has the suffix of ".action" please remove it**/
public String removeSuffix(String name){
if(name.endsWith(".action")){
name = name.substring(0,name.indexOf("."));
}else{
flag = false;
}
return name;
}
ActionStore类 只是暂存从路径中解析出来的namespace 和method。 最终从配置文件找出来的信息我存在了ActionMapping这个类中。
actionMapping.mapping();
这个类是从配置文件中根据路径信息找到匹配的变量值,将他们封装到actionMapping中。
package com.mapper;
import java.util.List;
import java.util.Map;
import com.dispatcher.Dispatcher;
import com.provide.XMLContextProvider;
import com.store.ActionStore;
import com.strust2.domain.ActionConfig;
import com.strust2.domain.PackageConfig;
import com.strust2.domain.ResultConfig;
import com.util.StringUtil;
public class ActionMapping {
private String namespace;
private String method;
private String name;
private String clazz;
private String type;
private ActionConfig actionConfig;
//in advance the result collection variable
private List<ResultConfig> resultConfigs;
// cache current result informations in to map
private Map<String,String> params;
public void mapping(){
String snamespace = ActionStore.getNamespace();
String name = ActionStore.getName();
XMLContextProvider provide = (XMLContextProvider) Dispatcher.getProviders().get("xmlContextProvider");
List<PackageConfig> packageConfs = provide.getPackageConfiguration();
getMappingNamespace(packageConfs,snamespace,name);
}
public void getMappingNamespace(List<PackageConfig> packageConfs,String snamespace,String method){
for(int i = 0; i < packageConfs.size(); i++){
PackageConfig packageConfig = packageConfs.get(i);
String tnamespace = packageConfig.getNamespace();
if(tnamespace.equals(snamespace)){
namespace = snamespace;
List<ActionConfig> actionConfigs = packageConfig.getActionConfs();
getMappingMethod(actionConfigs,method);
}
}
}
public void getMappingMethod(List<ActionConfig> actionConfigs,String name){
for(int i = 0; i <actionConfigs.size(); i++){
ActionConfig actionConfig = actionConfigs.get(i);
if(StringUtil.matches(actionConfig.getName(),name)){
this.actionConfig = actionConfig;
this.name = name;
this.clazz = actionConfig.getClazz();
convertion(name);
resultConfigs = actionConfig.getResultConfigs();
}
}
}
public void convertion(String name){
if(name.indexOf("_") != -1){
this.method = name.substring(name.indexOf("_")+1);
}else{
method = actionConfig.getMethod();
}
}
/** this method was something wrong*/
@Deprecated
public String getParambySpecial(String key){
return ActionStore.getParambySpecial(key);
}
/** get set methods */
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ActionConfig getActionConfig() {
return actionConfig;
}
public void setActionConfig(ActionConfig actionConfig) {
this.actionConfig = actionConfig;
}
public List<ResultConfig> getResultConfigs() {
return resultConfigs;
}
public void setResultConfigs(List<ResultConfig> resultConfigs) {
this.resultConfigs = resultConfigs;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void setParams(Map<String, String> params) {
this.params = params;
}
public Map<String, String> getParams() {
return params;
}
}
在上边我就需要用之前缓存好的Provider的类提供的方法去得到packageConfig变量了,这个变量封装了<package>标签下的全部的信息。 然后通过路径指明的namespace 和 name去匹配,得到指定 action of class and method.
上边我要讲讲当name以 xxx_method.action的形式,是如何处理的:
public void getMappingMethod(List<ActionConfig> actionConfigs,String name){
for(int i = 0; i <actionConfigs.size(); i++){
ActionConfig actionConfig = actionConfigs.get(i);
if(StringUtil.matches(actionConfig.getName(),name)){
this.actionConfig = actionConfig;
this.name = name;
this.clazz = actionConfig.getClazz();
convertion(name);
resultConfigs = actionConfig.getResultConfigs();
}
}
}
注意到if语句中的matches方法了吗,这里用正则表达式去判断符合那种情况。
//to convert target regex to regular expressions
public static boolean matches(String regex,String input){
//note: write the empty method to instead of finish it's function
regex = convertToRegExp(regex);
System.out.println(regex);
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
convertToRegExp方法:如果是有_下斜杠我就认为是xxx_method.action的形式。拆分,组装成正则表达似乎。如果不是,添加头尾符号返回
private static String convertToRegExp(String regex){
//if regex contain the character of "_" "^skip(_(\\w+))?$";
if(regex.indexOf("_")!=-1){
regex = regex.substring(0,regex.indexOf("_"));
regex = "^" + regex + "(_(\\w+))?$";
}else{
// add the first and end character like ^regex$";
regex = "^" + regex + "$";
}
return regex;
}
struts2源码的判断比较复杂,博主折中使用了这个简单的方法。
匹配好了,当然就要执行了
/** execute action and interceptor by this function**/
public void ActionService(ActionMapping actionMapping){
//through the agent for the calling ActionInvocation class
// if the path is not end with the suffix of ".action" ,will not execute agent
if(flag){
if(actionProxy == null){
actionProxy = new DefaultActionProxy();
}
List<Interceptor> interceptors = new ArrayList<Interceptor>();
ActionInvocation actionInvocation = new DefaultActionInvocation(interceptors,actionMapping);
actionProxy.setActionInvocation(actionInvocation);
actionProxy.execute();
}
}
创建代理类 然后赋予action执行类:DefaultActionInvocation。 我之前在想,action可以使用代理,那么我result执行也非得试一下代理,而且使用同一个代理类。 可以action 和 result之间有些差异啊,怎么办,我想到了接口,既然存在差异我就用接口统一
其差异在实现类表现。 所以这里有一个:DefaultResultInvocation的类实现这个ActionInvocation接口,这里不是命名不是很规范,这也是整体架构的难度。
下面请看 execute()所执行的方法:
public void execute() {
//I want to the DefaultActionProxy to use a variety
//of situations then using the interface,can provide
//a unified method
actionInvocation.invoke();
}
关键代码在invoke
package com.Invocation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import com.Interceptor.Interceptor;
import com.ireturn.IReBack;
import com.mapper.ActionMapping;
import com.proxy.ActionProxy;
import com.proxy.DefaultActionProxy;
import com.returnparam.ReturnParam;
import com.strust2.domain.ResultConfig;
public class DefaultActionInvocation implements ActionInvocation{
private List<Interceptor> interceptors;
private ActionMapping actionMapping;
private Integer index = 0;
public DefaultActionInvocation(List<Interceptor> interceptors,
ActionMapping actionMapping) {
this.interceptors = interceptors;
this.actionMapping = actionMapping;
}
public String invoke() {
//here we should get all the Interceptors and execute them
String result = null;
if(index < interceptors.size()){
Interceptor iterceptor = interceptors.get(index++);
result = iterceptor.interceptor(this);
}else{
//execute the the special class of action label
result = executeActionMethod();
//execute the result
executeResultMethod(result);
}
return result;
}
public String executeActionMethod(){
//here I need the class instance
actionMapping.mapping();
String classname = actionMapping.getClazz();
String methodname = actionMapping.getMethod();
String result = null;
try {
Class clazz = Class.forName(classname);
Object obj = clazz.newInstance();
Method method = clazz.getMethod(methodname, null);
result = (String)method.invoke(obj, null);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//here I need the method instance
return result;
}
public void executeResultMethod(String result){
//I need the instance special by type attribute
try {
String type = searchMappingResultType(actionMapping.getResultConfigs(),result);
String path = actionMapping.getParams().get(result);
type = ReturnParam.getReturnValue(type);
ActionProxy actionProxy = new DefaultActionProxy();
IReBack reBack = (IReBack) Class.forName(type).newInstance();
ActionInvocation resultInvocation = new DefaultResultInvocation(actionMapping,reBack,result,path);
actionProxy.setActionInvocation(resultInvocation);
actionProxy.execute();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private String searchMappingResultType(List<ResultConfig> resultConfigs,String result){
String type = null;
for(int i = 0;i < resultConfigs.size(); i++){
ResultConfig resultConfig = resultConfigs.get(i);
if(resultConfig.getParams().containsKey(result)){
type = resultConfig.getType();
actionMapping.setParams(resultConfig.getParams());
}
}
//if user fill out no type information
//use the default type of "dispatcher"
if(type == null){
type = "dispatcher";
}
return type;
}
}
这里有个链形式的递归,关于递归,之前我读struts2源码比较迷惑的地方,都在博客中做了了一些尝试性的探索记录。
这个递归的作用处理拦截器 和action之间的调用顺序。
关于action 如何执行就不多说了,从上边的方法可以看出执行ation method的方法,就异常处理代码多点。
下面讲讲result的处理
public void executeResultMethod(String result){
//I need the instance special by type attribute
try {
String type = searchMappingResultType(actionMapping.getResultConfigs(),result);
String path = actionMapping.getParams().get(result);
type = ReturnParam.getReturnValue(type);
ActionProxy actionProxy = new DefaultActionProxy();
IReBack reBack = (IReBack) Class.forName(type).newInstance();
ActionInvocation resultInvocation = new DefaultResultInvocation(actionMapping,reBack,result,path);
actionProxy.setActionInvocation(resultInvocation);
actionProxy.execute();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
actionMapping存储的只是当前action的result集,在这个actionMapping对象中定义一个Map<String,String> params
本来想在actionMapping()方法中将所有的result信息的存放到params中的,但是考虑到result有两种写法,其中一种写法不能讲name作为key,所以不得不写个搜索功能,在params中存储result的信息集合。
private String searchMappingResultType(List<ResultConfig> resultConfigs,String result){
String type = null;
for(int i = 0;i < resultConfigs.size(); i++){
ResultConfig resultConfig = resultConfigs.get(i);
if(resultConfig.getParams().containsKey(result)){
type = resultConfig.getType();
actionMapping.setParams(resultConfig.getParams());
}
}
//if user fill out no type information
//use the default type of "dispatcher"
if(type == null){
type = "dispatcher";
}
return type;
}
下面看一下结果代理:
package com.proxy;
import com.Invocation.ActionInvocation;
public class DefaultActionProxy implements ActionProxy {
private ActionInvocation actionInvocation;
public void execute() {
//I want to the DefaultActionProxy to use a variety
//of situations then using the interface,can provide
//a unified method
actionInvocation.invoke();
}
public ActionProxy getActionProxy() {
ActionProxy actionProxy = new DefaultActionProxy();
return null;
}
public ActionInvocation getActionInvocation() {
return actionInvocation;
}
public void setActionInvocation(ActionInvocation actionInvocation) {
this.actionInvocation = actionInvocation;
}
}
please see DefaultResultInvocation class
package com.Invocation;
import java.util.List;
import com.Interceptor.Interceptor;
import com.ireturn.IReBack;
import com.mapper.ActionMapping;
import com.util.PathUtil;
/*
* this class is implements the interface
* so we can enforcement unified method
* in the ActionProxy
*/
public class DefaultResultInvocation implements ActionInvocation{
private ActionMapping actionMapping;
private IReBack reBack;
private String result;
private String path;
public DefaultResultInvocation(ActionMapping actionMapping, IReBack reBack,String result,String path) {
this.actionMapping = actionMapping;
this.reBack = reBack;
this.result = result;
this.path = path;
}
public String invoke() {
path = "/"+path;
reBack.reBack(path);
return null;
}
}
ReBack是redirect ,dispatcher功能类所实现的接口,这里也是为了统一才设置接口的。
这里我只实现了dispatcher功能的类。
package com.ireturn;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.dispatcher.Dispatcher;
public class Struts2Dispatcher implements IReBack {
/** implements the interface method what you want to do*/
/** in other way we can derive request class,but it seems to implements some method */
public void reBack(String path) {
try {
//get the Request variable
HttpServletRequest request = (HttpServletRequest) Dispatcher.getScopes().get("request");
HttpServletResponse response = (HttpServletResponse) Dispatcher.getScopes().get("response");
//forward the request
request.getRequestDispatcher(path).forward(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里就需要得到之前缓存的静态变量scope集合了。从集合中得到作用域。
好了,基本是这些了,上边拦截器只提供了接口,实现类还是要靠用户实现的。 还是那句话功能实现人人都会,如何处理复杂的关系,如何巧妙搭设整个框架,我想,这是源码吸引我的地方