使用javassist高级反射调用任意参数的方法-模拟Struts2的实现
注:转自王健老师QQ空间。。。。很接地气的代码。。。。 URL:http://user.qzone.qq.com/549051701/blog/1466088405
使用javassist高级反射调用任意参数的方法-模拟Struts2的实现
1:核心过虑器
2:配置
3:配置action
4:开发Action任意类
5:测试
6:运行结果
say is ....org.apache.catalina.session.StandardSessionFacade@6747f5 //正确接收到Session
ClassPool高级反射
ClassPool反射出方法的所有参数。
必须要设置ClassPool加载的类路径即classPool.insertClassPath(...);
package cn.mystruts;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
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 javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMember;
import javassist.CtMethod;
/**
* 使用javassist高级反射动态调用任意方法的过虑器实现
* @author wangjian
*/
public class CoreFilter implements Filter {
private Document dom;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
try {
SAXReader reader = new SAXReader();
String pa = CoreFilter.class.getClassLoader().getResource("mystruts.xml").getPath();
System.err.println("p2 is:" + pa);
dom = reader.read(pa);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// url-pattern=/*
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
uri = uri.replace(req.getContextPath() + "/", "");
String action = "";
String methodName = "execute";//默认的方法名为execute
if (uri.contains("!")) {//如果在uri中包含 !即:one!say则解析出方法名为say
action = uri.substring(0, uri.indexOf("!"));
methodName = uri.substring(uri.indexOf("!") + 1);
} else {
action = uri;//默认action名称即为uri
}
// 取出one从dom中查询
String xpath = "//controller[@name='" + action + "']";
Element ele = (Element) dom.selectSingleNode(xpath);
try {
if (ele != null) {
// 如果配置过
// 解析且通过反射来执行它
String clsName = ele.attributeValue("class");
Class cls = Class.forName(clsName);
Object obj = cls.newInstance();
// 判断是否是Model的子类,设置参数
if (obj instanceof Model) {
Object bean = ((Model) obj).getBean();
BeanUtils.populate(bean, req.getParameterMap());
}
// 设置参数
BeanUtils.populate(obj, req.getParameterMap());
// 反射出方法的参数 - 通过高级反射javassist反射出方法
ClassPool cp = ClassPool.getDefault();
//设置从当前类目录下加载Class类
cp.insertClassPath(new ClassClassPath(this.getClass()));
CtClass ctClass = cp.get(cls.getName());
CtMethod ctMethod = ctClass.getDeclaredMethod(methodName);
int paramSize = ctMethod.getParameterTypes().length;
Class[] clses = new Class[paramSize];
for (int i = 0; i < paramSize; i++) {
clses[i] = Class.forName(ctMethod.getParameterTypes()[i].getName());
}
// 反射来执行它
Method method = cls.getMethod(methodName, clses);
//判断参数,并设置参数类型和参数值
Object[] paramObjs = new Object[paramSize];
for (int i = 0; i < paramSize; i++) {
for (int j = 0; j < 4; j++) {
if (clses[i] == HttpSession.class) {
paramObjs[i] = req.getSession();
}else if(clses[i] == HttpServletRequest.class){
paramObjs[i] = req;
}else{
Object ooBean = clses[i].newInstance();
paramObjs[i] = ooBean;
BeanUtils.populate(ooBean, req.getParameterMap());
}
}
}
String res = (String) method.invoke(obj,paramObjs);
// 执行完成了
if (obj instanceof Model) {
Object bean = ((Model) obj).getBean();
// user
req.setAttribute(bean.getClass().getSimpleName().toLowerCase(), bean);
}
req.setAttribute(obj.getClass().getSimpleName().toLowerCase(), obj);
if (res != null) {
// 找到page页面转 发
xpath += "/page[@name='" + res + "']";
Element page = (Element) dom.selectSingleNode(xpath);
if (page != null) {
String jsp = page.getText();
req.getRequestDispatcher(jsp).forward(request, response);
}
}
// 返回的这字符串表示的是
} else {// 如果没有找到则直接放行
// HttpServletResponse resp = (HttpServletResponse) response;
// resp.sendError(407, "没有配置【" + uri + "】这个action。。");
chain.doFilter(request, response);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void destroy() {
}
}
2:配置
<filter>
<filter-name>m2</filter-name>
<filter-class>cn.mystruts.CoreFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>m2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>3:配置action
<?xml version="1.0" encoding="UTF-8"?>
<mystruts>
<controller name="one" class="cn.mystruts.OneAction">
<page name="success">/jsps/show.jsp</page>
</controller>
</mystruts>4:开发Action任意类
package cn.mystruts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import cn.mystruts.domain.User;
/**
* 任意类,可以包含任意方法
* @author wangjian
*/
public class OneAction implements Model<User> {
private String name;
private User user = new User();
@Override
public User getBean() {
return user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String execute() {
System.err.println("user is:" + user);
user.setName("Alext新名称");
System.err.println("接收到的值是:" + name);
name = "修改以后的名称";
return "success";
}
// one!hi
public String hi() {
System.err.println("Hi....");
return "success";
}
public String say(HttpSession s) {
System.err.println("say is ...." + s);
return "success";
}
public String good(HttpSession s, HttpServletRequest req) {
System.err.println("good is ...." + s + ",req is:" + req);
return "success";
}
public String hello(HttpSession s, HttpServletRequest req, User u) {
System.err.println("hello is ...." + s + ",req is:" + req + ",user is:" + u);
return "success";
}
public String ok(User user){
System.err.println("in ok user is:"+user);
return "success";
}
}
5:测试
<a href="one!hi">调用OneActon.hi()</a>
<br>
<a href="one!say">调用OneAction.say(HttpSession)</a>
<br>
<a href="one!good">调用OneAction.good(HttpSessoin,HttpServletRequest)</a>
<br>
<a href="one!hello?name=Jack">调用OneAction.hello(HttpSession,HttpServletRequest,User)同时封装参数</a>6:运行结果
say is ....org.apache.catalina.session.StandardSessionFacade@6747f5 //正确接收到Session
good is ....org.apache.catalina.session.StandardSessionFacade@6747f5,req is:org.apache.catalina.connector.RequestFacade@1bd42e8 //正确接收到Session,Request
hello is ....org.apache.catalina.session.StandardSessionFacade@6747f5,req is:org.apache.catalina.connector.RequestFacade@1bd42e8,user is:User [name=Jack, age=null]//正确接收到Session,Req,Bean
小结:ClassPool高级反射
ClassPool反射出方法的所有参数。
必须要设置ClassPool加载的类路径即classPool.insertClassPath(...);