自己动手撸一个 MVC 控制器
用来加深对java反射的理解的练手项目 也是加深对spring MVC 理解的项目
Mappping 对象
import java.lang.reflect.Method;
/**
* 用于存储每个url映射
*
* @author : xiaohai
* @date : 2019/03/17 20:58
*/
public class Mapping {
private String[] path;
private String requestMethod;// 请求方式
private Class<?> aclass;
private Method method;//注解对应的methods
//setter and getter
}
RequestMapping注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface RequestMapping {
String[] value() default "";
RequestMethod method() default RequestMethod.GET;
}
Controller注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Controller {
String value() default "";
}
核心servlet
import cn.celess.boot.Application;
import cn.celess.boot.annotation.Controller;
import cn.celess.boot.annotation.RequestMapping;
import cn.celess.boot.entity.Mapping;
import cn.celess.boot.util.*;
import cn.celess.logtool.Log;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author : xiaohai
* @date : 2019/03/17 10:16
* 核心控制类
*/
public class DispatcherServlet extends HttpServlet {
private static final Log log = new Log(DispatcherServlet.class);
private static final List<Mapping> mappingList = new ArrayList<Mapping>();
public DispatcherServlet() {
initRequestMapingMap(Application.classpath);
}
/**
* 解析 获取请求的参数 即RequestMapping的value值和method
* 对path进行整理 保存为/xx/xx/的格式
*
* @param request
* @return
*/
private String[] pareUrl(HttpServletRequest request) {
String[] pAndM = new String[2];
String path = request.getContextPath() + "/";
String requestUri = request.getRequestURI().replaceFirst(path, "");
if (requestUri.length() > 0) {
if (requestUri.substring(requestUri.length() - 1) != "/") {
requestUri += "/";
}
} else {
requestUri += "/";
}
pAndM[0] = "/" + requestUri;
pAndM[1] = request.getMethod();
return pAndM;
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
log.info("执行了service方法");
this.execute(req, resp);
}
/**
* 匹配path和RequestMethod 并执行path匹配的方法
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String[] s = pareUrl(request);
String urlPath = s[0];
String requestMethod = s[1];
Class<?> clazz = null;
Method method = null;
for (Mapping ml : mappingList) {
String[] path = ml.getPath();
for (String str : path) {
if (urlPath.equals(str)) {
if (requestMethod.toUpperCase().equals(ml.getRequestMethod())) {
method = ml.getMethod();
clazz = ml.getAclass();
break;
}
}
}
if (method != null) break;
}
if (method == null) {
response.sendError(404);//没找到映射
return;
}
Object obj = null;//方法返回值
if (method != null) {
Object retObject = null;
try {
//创建类的实例
obj = clazz.newInstance();
//利用反射执行这个方法
retObject = method.invoke(obj, request, response);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
/***
* 将controller 解析然后存储起来
* @param packageName
*/
private void initRequestMapingMap(String packageName) {
List<Class> classList = ReflectUtil.getClasssFromPackage(packageName);
for (Class c : classList) {
if (c.isAnnotationPresent(Controller.class)) {
Method[] methods = c.getDeclaredMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(RequestMapping.class)) {
String[] path = m.getAnnotation(RequestMapping.class).value();
// 对path 进行 规范化
for (int i = 0; i < path.length; i++) {
if (!"/".equals(path[i].substring(0, 1))) {
path[i] = "/" + path[i];
}
if (!"/".equals(path[i].substring(path[i].length() - 1))) {
path[i] += "/";
}
}
String requestMethod = m.getAnnotation(RequestMapping.class).method().getMethod();
log.info("path : " + Arrays.toString(path) + " requestMethod:" + requestMethod);
Mapping mapping = new Mapping();
mapping.setPath(path);
mapping.setRequestMethod(requestMethod);
mapping.setAclass(c);
mapping.setMethod(m);
mappingList.add(mapping);
}
}
}
}
log.info("方法映射成功");
}
}
欢迎关注我的博客 小海博客