看懂本文前提
- 需要一点点的java基础
- 需要一点点反射基础
- 没有了
先大概讲讲废话,代码是当初学反射的时候自己想的示例,有些请求地址与方法间的映射判断忽略,在代码里写死了.
SpringMVC在启动的时候扫描注解,将Mapping于方法统一维护起来,在请求的时候通过路径匹配选择调用方法. Spring中可以通过下面代码查看所有请求接口及对应方法
@Autowired
private ApplicationContext applicationContext;
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
mapping.getHandlerMethods();// 接口路径--方法的关系
不说废话了,看码…
之前学习时候的工程已经起不来了,把关键代码贴了出来,
- 仿的被Spring管理的Conller 类
public class Kk {
/**
* 仿的Conller 方法
* @param user
* @param page
*/
public void test(PracticeUser user, Page page) {
System.out.println(user);
System.out.println(page);
}
}
- URL接口类
// 一些于当前功能没关系的都上了
@GetMapping("/getPracticeUserList.ht")
@ResponseBody
public LayuiTabltBody getPracticeUserList(HttpServletRequest request , HttpServletResponse response, Page page) {
//模仿实现参数接受
//方法所在的类,框架内根据参数可以获取到
Class<Kk> aClass = Kk.class;
//对应的方法名
String methodName = "test";
try {
kkUtli.test1(aClass, methodName,request,response);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
仿写Spring处理类
@Component
public class KkUtli {
/**
* Class的test方法中的参数的属性只能是
* java.lang.Integer
* java.lang.Long
* java.util.Date ( "yyyy-MM-dd" AND "yyyy-MM-dd HH:mm:ss" )
* java.lang.String
* 四种类型
* 参数不支持 无无参构造方法的数据类型
*
* @param Class
* @param methodName
* @param request
* @param response
* @throws Exception
*/
public void test1(Class Class, String methodName, HttpServletRequest request, HttpServletResponse response)
throws Exception {
//获取参数列表
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keySet = parameterMap.keySet();
//获取某个方法
Method method = null;
Method[] declaredMethods = Class.getDeclaredMethods();
for (Method m : declaredMethods) {
if (m.getName().equals(methodName)) {
method = m;
break;
}
}
//获取对象类实例
Object object = Class.newInstance();
// ObjectMapper mapper = new ObjectMapper();
// mapper.convertValue(object, Class);
//获取这个方法的参数列表
java.lang.Class<?>[] parameterTypes = method.getParameterTypes();
// 用来存实例化好的参数
List list = new ArrayList();
// 便利参数列表
for (Class c : parameterTypes) {
//实例化参数
Object o = c.newInstance();
//获取参数列表
Field[] fields = c.getDeclaredFields();
//参数名字链表
Set<String> stringSet = new HashSet<>();
for (Field field : fields) {
stringSet.add(field.getName());
}
//获取交集
stringSet.retainAll(keySet);
//遍历交集 表示该参数中的实体中有字段在参数中需要封装存在
for (String name : stringSet) {
Method[] methods = c.getDeclaredMethods();
for (Method m : methods) {
if (("set" + upperCase(name)).equals(m.getName())) {
java.lang.Class<?> types = m.getParameterTypes()[0];
Method setPage = c.getMethod("set" + upperCase(name), types);
setPage.invoke(o, getArg(parameterMap, name, types));
break;
}
}
}
//放入list中
list.add(o);
}
//转换格式
Object[] objects = list.toArray();
method.invoke(object, objects);
}
/**
* 首字母大写转换
*
* @param str
* @return
*/
public static String upperCase(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
public static Object getArg(Map<String, String[]> parameterMap, String name, Class<?> types) throws Exception {
String s = parameterMap.get(name)[0];
Object re;
switch (types.getName()) {
case "java.lang.Integer":
re = Integer.valueOf(s);
break;
case "java.lang.Long":
re = Long.valueOf(s);
break;
case "java.util.Date":
java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd");
if (s.length() != 10) {
java.text.SimpleDateFormat fat= new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = fat.parse(s);
s = formatter.format(date);
}
re = formatter.parse(s);
break;
default:
re = s;
}
return re;
}
}
代码都贴完了,现在讲下思路好了,
通过反射获得方法的参数列表,于请求中的参数列表进行匹配,如果相匹配则通过反射写入,
当所有参数列表都判断完成后,通过反射调用指定方法.
访问连接 后即可将参数分钟值对应的实体类中http://localhost:8888/user/super/getPracticeUserList.ht?page=88&limit=2&account=%E8%B4%A6%E5%8F%B7
控制台打印效果
代码中 变量命名不是很规范懒得改都,都是以前学习时候写的,不过注释都齐全,希望对感兴趣的人有所帮助!