拦截器Interceptor
在上节所做的简单控制器的基础上,插入拦截器功能,通过读取解析xml文件中的标签配置,分发请求给特定的拦截器处理类进行处理。
SimpleController工程
SimpleController工程目录:
ActionBean以及InterceptorBean是抽象出的两个普通java类,分别对应action以及Interceptor以便于以后扩展功能。
ActionBean.java
ActionBean中定义了一个action的内容,例如action的name,action请求的处理类,方法,结果等。当有一个请求过来时,会生成一个对应的ActionBean对象。代码如下:
package sc.ustc.bean;
import java.util.List;
import java.util.Map;
public class ActionBean {
private String actionName;
private String actionClass;
private String actionMethod;
private Map<String, List<String>> actionResults;
private Map<String, List<String>> actionInterceptors;
public ActionBean(String actionName, String actionClass, String actionMethod, Map<String, List<String>> actionResults,
Map<String, List<String>> actionInterceptors) {
this.actionName = actionName;
this.actionClass = actionClass;
this.actionMethod = actionMethod;
this.actionResults = actionResults;
this.actionInterceptors = actionInterceptors;
}
//属性的get set方法就不贴出来了
}
InterceptorBean.java
同样的有InterceptorBean。代码如下:
package sc.ustc.bean;
public class InterceptorBean {
private String interceptorName;
private String interceptorClass;
private String interceptorPredo;
private String interceptorAfterdo;
public InterceptorBean(String interceptorName, String interceptorClass, String interceptorPredo, String interceptorAfterdo) {
this.interceptorName = interceptorName;
this.interceptorClass = interceptorClass;
this.interceptorPredo = interceptorPredo;
this.interceptorAfterdo = interceptorAfterdo;
}
//属性的get set方法就不贴出来了
}
MyTools.java
与上一节不同,这里xml文件的解析采取了DOM方式,上一节的解析方式针对性比较强,xml文件的内容必须按照设计好的格式写,DOM方式是java提供的一种基础的解析XML文件的API,用起来很方便,但是由整个文件都需要载入内存所以对内存的消耗较大。
package sc.ustc.tool;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import sc.ustc.bean.ActionBean;
public class MyTools {
public ActionBean readXml_dom(String actionName, String path) {
try {
// controller.xml解析(DOM)
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder buillder = dbf.newDocumentBuilder();
Document doc = buillder.parse(new File(path));
// 解析interceptor节点
NodeList interceptorsLi = doc.getElementsByTagName("interceptor");
Map<String, List<String>> InterceptorMap = new HashMap<String, List<String>>();
for (int i = 0; i < interceptorsLi.getLength(); i++) {
List<String> interDirts = new ArrayList<String>();
Element interceptor = (Element) interceptorsLi.item(i);
interDirts.add(interceptor.getAttribute("name"));
interDirts.add(interceptor.getAttribute("class"));
interDirts.add(interceptor.getAttribute("predo"));
interDirts.add(interceptor.getAttribute("afterdo"));
InterceptorMap.put(interceptor.getAttribute("name"), interDirts);
}
// 解析action节点
NodeList actions = doc.getElementsByTagName("action");
for (int i = 0; i < actions.getLength(); i++) {
Element action = (Element) actions.item(i);
if (action.getAttribute("name").equals(actionName)) {
// 获取result节点
Map<String, List<String>> actionResultMap = new HashMap<String, List<String>>();
NodeList results = action.getElementsByTagName("result");
for (int j = 0; j < results.getLength(); j++) {
Element childNode = (Element) results.item(j);
List<String> resultList = new ArrayList<String>();
resultList.add(childNode.getAttribute("name"));
resultList.add(childNode.getAttribute("type"));
resultList.add(childNode.getAttribute("value"));
actionResultMap.put("result" + childNode.getAttribute("name"), resultList);
}
// 获取interceptor节点
Map<String, List<String>> actionInterceptors = new HashMap<String, List<String>>();
NodeList interceptors = action.getElementsByTagName("interceptro-ref");
for (int j = 0; j < interceptors.getLength(); j++) {
Element childNode = (Element) interceptors.item(j);
actionInterceptors.put(String.valueOf(j), InterceptorMap.get(childNode.getAttribute("name")));
}
return new ActionBean(actionName, action.getAttribute("class"), action.getAttribute("method"), actionResultMap, actionInterceptors);
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
SimpleController.java
SimpleController接收到所有的action,解析name,class,method,通过java反射机制调用相应的类进行处理。同样的,会先判断是否有Interceptor,若有则先处理一层层的Interceptor。
package sc.ustc.controller;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sc.ustc.bean.ActionBean;
import sc.ustc.tool.CglibProxy;
import sc.ustc.tool.MyTools;
public class SimpleController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@SuppressWarnings("unchecked")
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html,charset=utf-8");
response.setCharacterEncoding("utf-8");
request.setCharacterEncoding("utf-8");
String actionName = request.getServletPath().toString();
String[] actionUrl = actionName.split("/");
actionName = actionUrl[actionUrl.length - 1];
String path = this.getServletContext().getRealPath("WEB-INF/classes/controller.xml");
MyTools mt = new MyTools();
ActionBean actionBean = mt.readXml_dom(actionName.substring(0, actionName.indexOf(".")), path);
if (actionBean != null) {
String actionClass = actionBean.getActionClass();
String actionMethod = actionBean.getActionMethod();
try {
// 反射机制获得action类名及方法
Class cl = Class.forName(actionClass);
Method m = cl.getMethod(actionMethod, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class);
String result = null;
/*
* 判断action是否有interceptor
*
* 待扩展,此处默认只有一个拦截器
*/
if (actionBean.getActionInterceptor() != null && !actionBean.getActionInterceptor().isEmpty()) {
// 创建代理实例
Object clc = CglibProxy.getProxy(cl);
// 调用代理方法
result = (String) m.invoke(clc, request, response, actionBean);
} else {
result = (String) m.invoke(cl, request, response, actionBean);
}
String resT = actionBean.getActionResults().get("result" + result).get(1);
String resV = actionBean.getActionResults().get("result" + result).get(2);
if (resT.equals("foward")) {
request.getRequestDispatcher(resV).forward(request, response);
} else if (resT.equals("redirect")) {
response.sendRedirect(resV);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
response.sendRedirect("/UseSC/jsp/Login.jsp");
}
}
}
CglibProxy.java
Cglib实现对业务处理类的代理,即进行拦截操作
package sc.ustc.tool;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import sc.ustc.bean.ActionBean;
public class CglibProxy {
public static Object getProxy(Class<?> clazz) {
CglibProxyX proxy = new CglibProxyX();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(proxy);
return enhancer.create();
}
}
class CglibProxyX implements MethodInterceptor {
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
ActionBean actionBean = (ActionBean) args[2];
String classN = actionBean.getActionInterceptor().get("0").get(1);
String predo = actionBean.getActionInterceptor().get("0").get(2);
String afterdo = actionBean.getActionInterceptor().get("0").get(3);
Class<?> cl = Class.forName(classN);
Method preMethod = cl.getMethod(predo, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class);
Method afterMethod = cl.getMethod(afterdo, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class, String.class);
preMethod.invoke(cl.newInstance(), (HttpServletRequest) args[0], (HttpServletResponse) args[1], actionBean);
String result = (String) proxy.invokeSuper(object, args);
afterMethod.invoke(cl.newInstance(), (HttpServletRequest) args[0], (HttpServletResponse) args[1], actionBean, result);
return result;
}
}
对应的配置文件示例
<?xml version="1.0" encoding="UTF-8"?>
<sc-configuration>
<interceptor name="log" class="water.ustc.interceptor.LogInterceptor"
predo="preAction" afterdo="afterAction">
</interceptor>
<controller>
<action name="login" class="water.ustc.action.LoginAction"
method="handleLogin">
<interceptro-ref name="log"></interceptro-ref>
<result name="success" type="foward" value="success_view.xml"></result>
<result name="failure" type="redirect" value="Login.jsp"></result>
</action>
<action name="regist" class="water.ustc.action.RegisterAction"
method="handleRegist">
<interceptro-ref name="log"></interceptro-ref>
<result name="success" type="foward" value="Welcome.jsp"></result>
<result name="failure" type="redirect" value="Regist.jsp"></result>
</action>
</controller>
</sc-configuration>
相应的UseSC工程部分的测试代码就不再详述了,与上一节类似
至此,写一个功能及其简陋的Struts框架系列完结