package com.bawei.yjy.mvc;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.bawei.yjy.mvc.annotation.RequestParam;
import com.bawei.yjy.mvc.annotation.ResponseBody;
/**
* 对url进行业务处理,并给前端控制器返回处理结果
* @author lizhangyong@bawei
*
*/
public class HandlerAdapter {
//使用泛型方法
public <T> T handlerAdapter(String url, HttpServletRequest req, HttpServletResponse res) {
res.setCharacterEncoding("utf-8");
res.setContentType("text/html;UTF-8");
HandlerMapping handlerMapping = new HandlerMapping();
// 判断handlerMapping.urlMethodMap里,是否包含要处理的url;包含时才会处理
if (handlerMapping.urlMethodMap.containsKey(url)) {
// 根据url获取对应的处理方法全路径,格式为 类全限定名:方法名
String controllerMethod = HandlerMapping.urlMethodMap.get(url);
String[] split = controllerMethod.split(":", 3);
try {
// 通过反射,基于类的全限定名获取其Class对象,并创建对象
//System.out.println(split[0]);
Class<?> clazz = Class.forName(split[0]);
Object obj = clazz.newInstance();
Method[] methods = clazz.getMethods();
Method method = null;
// 判断是否找到真正对应处理url的方法,解决方法重载问题——默认方法名和参数均存在
boolean mathodExsit = true;
boolean paramExist=true;
Parameter[] parameters =null;
for (Method m : methods) {
//System.out.println(split[1]+"--"+m.getName());
//判断方法名是否一致,名称一致时再判断参数是否一致
if (split[1].equals(m.getName())) {
//System.out.println(split[1]+"--"+m.getName());
parameters = m.getParameters();
if(null==split[2] || "".equals(split[2])) {
method=m;
paramExist=false;
break;
}
String[] paramSplit = split[2].split("-");
if (paramSplit.length == parameters.length) {
//System.out.println(paramSplit.length+"--"+parameters.length);
for (int i = 0; i < paramSplit.length; i++) {
if (!paramSplit[i].equals(parameters[i].getType().getSimpleName())) {
mathodExsit = false;
}
}
//如果方法名与参数均一致,则找到了需要的方法;否则继续找
if (mathodExsit) {
method = m;
break;
} else {
mathodExsit=true;
continue;
}
} else {
continue;
}
}else {continue;}
}
//如果未找到对应的处理方法,则结束
if(method==null) {
writeWarn(res, url);
return null;
}
//如果方法存在,则执行方法,返回结果——如果方法无参,反射调用方法执行时,无需传入参数,否则传参
Object result = null;
if(paramExist==false) {
result=method.invoke(obj);
}
Object[] paramValues = new Object[parameters.length];
String simpleTypeName = null;
for (int i = 0; i < parameters.length; i++) {
simpleTypeName = parameters[i].getType().getSimpleName();
if ("HttpServletRequest".equals(simpleTypeName)) {
paramValues[i] = req;
continue;
} else if ("HttpServletResponse".equals(simpleTypeName)) {
paramValues[i] = res;
continue;
} else {
if (parameters[i].isAnnotationPresent(RequestParam.class)) {
RequestParam annotation = parameters[i].getDeclaredAnnotation(RequestParam.class);
if ("".equals(annotation.value())) {
// System.out.println(parameters[i].getName());
String paramReq = req.getParameter(parameters[i].getName());
if (paramReq != null) {
paramValues[i] = paramReq;
}else {
magicAssign(i, paramValues, parameters);
}
} else {
if (req.getParameter(annotation.value()) != null) {
paramValues[i] = req.getParameter(annotation.value());
}else {
magicAssign(i, paramValues, parameters);
}
}
} else {
magicAssign(i, paramValues, parameters);
}
}
}
//反射调用方法时,会传入该方法的所有实参,这些实参需要进行初始化
result = method.invoke(obj, paramValues);
Object resultFinal = judgeReturnType(result, method, res);
if(resultFinal==null) {
return null;
}else {
//System.out.println(resultFinal.getClass().getSimpleName());
return (T) resultFinal;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
writeWarn(res, url);
}
return null;
}
private void writeWarn(HttpServletResponse res,String url) {
try {
res.getWriter().write("<div style='margin:15px auto auto 55px;width:60%;color:#DC143C;font-weight:bold;'>"
+ "<h3>抱歉,映射此方法的url:"+url+"未找到。</h3><h4>请再次尝试。</h4>"
+"<hr style='margin-left:0px;'>"
+ "<h3>抱歉,映射此方法的url:"+url+"未找到。</h3><h4>請再次嘗試。</h4>"
+"<hr style='margin-left:0px;'>"
+ "<h3>이 방법을 사용할 수 없습니다"+url+"찾을 수 없습니다.</h3><h4>다시 한 번 시도해 보세요. </h4>"
+"<hr style='margin-left:0px;'>"
+ "<h3>申し訳ございません、この方法のurl:"+url+"見つからない。</h3><h4>もう一度やってみてください。</h4>"
+"<hr style='margin-left:0px;'>"
+"<h3>Sorry,the method mapping this url:"+url+" not found.</h3><h4>Please try again!</h4>"
+"</div>"
);
} catch (IOException e) {
e.printStackTrace();
}
}
//判断返回值的类型
private Object judgeReturnType(Object result,Method method, HttpServletResponse res) {
if(result!=null) {
//获取返回值的类型
Type returnType = method.getGenericReturnType();
//System.out.println(returnType);
//先判断是否返回ModelAndView
if(returnType.getTypeName().equals(ModelAndView.class.getName())) {
return (ModelAndView)result;
}
//再判断是否返回json数据
else if (method.isAnnotationPresent(ResponseBody.class)) {
String jsonString = JSONObject.toJSONString(result);
return jsonString;
} else {
try {
res.getWriter().write("<div style='margin:15px auto auto 55px;width:60%;color:#708090'>使用非法!<br>" +
"本框架优先识别方法的返回类型为ModelAndeView;" +
"其次识别@ResponseBody注解。<br>" +
"当使用@ResponseBody注解时,返回类型不限。<br>" +
"请遵守上述使用规则。<hr style='margin-left:0px;'>"
+"使用非法!<br>" +
"本框架優先識別方法的返回類型為ModelAndeView;" +
"其次識別@ResponseBody注解。<br>" +
"當使用@ResponseBody注解時,返回類型不限。<br>" +
"請遵守上述使用規則。<hr style='margin-left:0px;'> "
+"불법 사용!<br>" +
"이 프레임의 우선적인 인식 방법의 귀환 유형은 모디앤드득템." +
"식 인식 @ @ Risponsu 보이디의 설명.<br>" +
"@ @ Risponsu 보이디를 사용할 때 유형을 되돌려줍니다.<br>" +
奔跑在梦想的道路上
- 粉丝: 104
- 资源: 7
最新资源
- gps追踪器源码和pcb资料,量产资料,可以直接生产用
- flash spi w25q128 w25q64 w25q32 w25q16 verilog fpga程序代码 fpga w25q128 64 32 16 verilog代码 资料包清单: 1.w2
- 全国计算机等级考试《三级数据库技术》复习核心内容讲解与备考指导
- 弯管机程序使用三菱FX系列 PLC和昆仑通态触摸屏,也可以用三菱F940系列触摸屏
- 信捷PLC上位机源代码例子,modbusTCP通信,通俗易懂,C#源代码
- 关于粒子滤波在电力负荷预测中的应用 python源代码,代码按照高水平文章复现,有详细说明,保证正确 在线预测电力负荷,在贝叶斯框架的动态模型 提供了顺序蒙特卡罗方法的回顾,并提供了所谓的粒子过滤
- 能源价格风险管理matlab源代码,代码按照高水平文章复现,保证正确 电力价格的波动性远远大于其他通常以极端波动著称的价格 由于电力不能经济地储存,终端用户的需求在很大程度上取决于天气,而电网的可靠
- 电力市场中生产者的战略招标:一种凸松弛方法matlab 源代码,代码按照高水平文章复现,保证正确 电力市场中的战略投标问题在电力系统中得到了广泛研究,通常是通过制定难以解决的复杂的双层优化问题来进行的
- FMC ADC12D2000RF 模块,忍痛出射频直接采集FMC ADC模块,模块基于Ti公司高端ADC12D2000RF芯片,芯片为单通道4GSPS,双通道2GSPS,12bit分辨率,这款芯片国
- 西门子200smart与施耐德ATV变频器modbus通讯 西门子s7-200smart与施耐德ATV12变频器通讯,可靠稳定,同时解决施耐德ATV变频器断电重启后,自准备工作,无需人为准备 器件:
- 2025/1/15 自用
- siddhi 的核心jar
- 上市公司的高压软启动控制源码,源码,需要的联系,平台TI,厂家见图,也有低压软起动的方案,
- 基于Atrix7 Kitex7 Vertex7系列FPGA的DDR3内存驱动器代码(Verilog语言),把2GB的内存做成一个可以同时读写的大型FIFO 有代码,有测试文档
- 圈乘问题求解问题pdf
- 关于配电网调压通信的需求VoltVAR反馈控制法则的比较完全分散与网络化策略 matlab源代码 代码按照高水平文章复现,保证正确 我们首先介绍了一类非常普遍的纯局部控制策略,并通过一个反例演示
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈