introducción
Código github: HTTPS: //github.com/erlieStar/servlet-learning
rama V3
El uso de un servlet 3.0 web.xml por lo que no tenemos, y toma notas
Nota definido
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
String value() default "";
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String value() default "";
}
controlador central definida
Sustancialmente la totalidad de la lógica en esta clase, el siguiente proceso principal
- Creación de tiempo DispatcherServlet, tomcat llamará al método init (), asignación de dirección URL en el que la inicialización de procesamiento de método y correspondiente
- Cuando una solicitud para el método de llegar desde el uriInvokeInfoMap correspondiente, si existe un método correspondiente, el método de reflexión se llama para obtener el nombre de la página, la costura dirección de la página, se remitirá a la página correspondiente, de lo contrario 404
@WebServlet(urlPatterns="/", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
// 保存所有的handler
private List<Object> beanList = new ArrayList<>();
// 保存 uri 和 handler 的映射关系
private Map<String, InvokeInfo> uriInvokeInfoMap = new HashMap<>();
private static final String SLASH = "/";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uri = req.getRequestURI();
String contextPath = req.getContextPath();
// 去掉项目路径
uri = uri.replace(contextPath, "");
System.out.println(uri);
if (uri == null) {
return;
}
InvokeInfo invokeInfo = uriInvokeInfoMap.get(uri);
if (invokeInfo == null) {
resp.getWriter().write("404");
return;
}
String pageName = (String)methodInvoke(invokeInfo.getBean(), invokeInfo.getMethod());
viewResolver(pageName, req, resp);
}
// 视图解析器
public void viewResolver(String pageName, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String prefix = "/";
String suffix = ".jsp";
req.getRequestDispatcher(prefix + pageName + suffix).forward(req, resp);
}
// 反射执行方法
private Object methodInvoke(Object object, Method method) {
try {
return method.invoke(object);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public void init() throws ServletException {
// 获取指定包下的Class对象
List<Class<?>> classList = ClassUtil.getAllClassByPackageName("com.javashitang.controller");
// 找到所有标注了@Controller的类
findAllConrollerClass(classList);
// 初始化 uri 和 handler 的映射关系
handlerMapping();
}
public void findAllConrollerClass(List<Class<?>> list) {
list.forEach(bean -> {
// 将被@Controller注解修饰的类放到beanList
if (bean.isAnnotationPresent(Controller.class)) {
try {
beanList.add(bean.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// 根据url找到相应的处理类
public void handlerMapping() {
for (Object bean : beanList) {
Class<? extends Object> classInfo = bean.getClass();
// 获取类上的@RequestMapping信息
RequestMapping beanRequestMapping = classInfo.getDeclaredAnnotation(RequestMapping.class);
String baseUrl = beanRequestMapping != null ? beanRequestMapping.value() : "";
Method[] methods = classInfo.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
// 获取方法上的@RequestMapping信息
RequestMapping methodRequestMapping = method.getDeclaredAnnotation(RequestMapping.class);
if (methodRequestMapping != null) {
String requestUrl = SLASH + baseUrl + SLASH + methodRequestMapping.value();
// 为了处理@Controller和@RequestMapping value 中加了 / 前缀的情况
requestUrl = requestUrl.replaceAll("/+", "/");
InvokeInfo invokeInfo = new InvokeInfo(bean, method);
uriInvokeInfoMap.put(requestUrl, invokeInfo);
}
}
}
}
}
El método y el correspondiente a una clase de bit no envasado
public class InvokeInfo {
private Object bean;
private Method method;
public InvokeInfo(Object bean, Method method) {
this.bean = bean;
this.method = method;
}
}
Para iniciar la prueba
@Controller
@RequestMapping("index")
public class IndexController {
@RequestMapping("user")
public String user() {
return "user";
}
}
Visitan las siguientes conexiones muestran correctamente
http://localhost:8080/show/index/user
atención de bienvenida
el blog de referencia
[1] https://my.oschina.net/liughDevelop/blog/1622646
[2] https://www.malaoshi.top/show_1EFutw6imbI.html