#22 mvc: annotation based
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
package org.example.mvc;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class AnnotationHandler {
|
||||||
|
private final Class<?> clazz;
|
||||||
|
private final Method tagetMethod;
|
||||||
|
|
||||||
|
public AnnotationHandler(Class<?> clazz, Method targetMethod) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.tagetMethod = targetMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
|
||||||
|
Object handler = declaredConstructor.newInstance();
|
||||||
|
|
||||||
|
return (String) tagetMethod.invoke(handler, request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.example.mvc;
|
||||||
|
|
||||||
|
import org.example.mvc.view.ModelAndView;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public class AnnotationHandlerAdapter implements HandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public boolean supports(Object handler) {
|
||||||
|
return handler instanceof AnnotationHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
String viewName = ((AnnotationHandler) handler).handle(request, response);
|
||||||
|
return new ModelAndView(viewName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package org.example.mvc;
|
||||||
|
|
||||||
|
import org.example.mvc.annotation.Controller;
|
||||||
|
import org.example.mvc.annotation.RequestMapping;
|
||||||
|
import org.example.mvc.controller.HandlerKey;
|
||||||
|
import org.example.mvc.controller.RequestMethod;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AnnotationHandlerMapping implements HandlerMapping {
|
||||||
|
|
||||||
|
private final Object[] basePackage;
|
||||||
|
|
||||||
|
private Map<HandlerKey, AnnotationHandler> handlers = new HashMap<>();
|
||||||
|
|
||||||
|
public AnnotationHandlerMapping(Object... basePackage) {
|
||||||
|
this.basePackage = basePackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
Reflections reflections = new Reflections(basePackage);
|
||||||
|
|
||||||
|
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(Controller.class);
|
||||||
|
|
||||||
|
classes.forEach(clazz -> {
|
||||||
|
Arrays.stream(clazz.getDeclaredMethods()).forEach(method -> {
|
||||||
|
RequestMapping requestMapping = method.getDeclaredAnnotation(RequestMapping.class);
|
||||||
|
|
||||||
|
Arrays.stream(getRequestMethods(requestMapping))
|
||||||
|
.forEach(requestMethod -> handlers.put(
|
||||||
|
new HandlerKey(requestMethod, requestMapping.value()), new AnnotationHandler(clazz, method)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestMethod[] getRequestMethods(RequestMapping requestMapping) {
|
||||||
|
return requestMapping.method();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object findHandler(HandlerKey handlerKey) {
|
||||||
|
return handlers.get(handlerKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.example.mvc;
|
package org.example.mvc;
|
||||||
|
|
||||||
import org.example.mvc.controller.Controller;
|
|
||||||
import org.example.mvc.controller.HandlerKey;
|
import org.example.mvc.controller.HandlerKey;
|
||||||
import org.example.mvc.controller.RequestMethod;
|
import org.example.mvc.controller.RequestMethod;
|
||||||
import org.example.mvc.view.JspViewResolver;
|
import org.example.mvc.view.JspViewResolver;
|
||||||
@@ -10,7 +9,6 @@ import org.example.mvc.view.ViewResolver;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.servlet.RequestDispatcher;
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.annotation.WebServlet;
|
import javax.servlet.annotation.WebServlet;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
@@ -18,7 +16,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@WebServlet("/")
|
@WebServlet("/")
|
||||||
@@ -26,16 +23,27 @@ public class DispatcherServlet extends HttpServlet {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);
|
private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);
|
||||||
|
|
||||||
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
private List<HandlerMapping> handlerMappings;
|
||||||
private List<ViewResolver> viewResolvers;
|
private List<ViewResolver> viewResolvers;
|
||||||
private List<HandlerAdapter> handlerAdapters;
|
private List<HandlerAdapter> handlerAdapters;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws ServletException {
|
public void init() throws ServletException {
|
||||||
requestMappingHandlerMapping = new RequestMappingHandlerMapping();
|
RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
|
||||||
requestMappingHandlerMapping.init();
|
requestMappingHandlerMapping.init();
|
||||||
|
|
||||||
handlerAdapters = List.of(new SimpleControllerHandlerAdaptor());
|
AnnotationHandlerMapping annotationHandlerMapping = new AnnotationHandlerMapping();
|
||||||
|
annotationHandlerMapping.init();
|
||||||
|
|
||||||
|
handlerMappings = List.of(
|
||||||
|
requestMappingHandlerMapping,
|
||||||
|
annotationHandlerMapping
|
||||||
|
);
|
||||||
|
|
||||||
|
handlerAdapters = List.of(
|
||||||
|
new SimpleControllerHandlerAdapter(),
|
||||||
|
new AnnotationHandlerAdapter()
|
||||||
|
);
|
||||||
viewResolvers = Collections.singletonList(new JspViewResolver());
|
viewResolvers = Collections.singletonList(new JspViewResolver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,9 +51,15 @@ public class DispatcherServlet extends HttpServlet {
|
|||||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
log.info("[DispatcherServlet] service started.");
|
log.info("[DispatcherServlet] service started.");
|
||||||
|
|
||||||
|
String requestURI = req.getRequestURI();
|
||||||
|
RequestMethod requestMethod = RequestMethod.valueOf(req.getMethod());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Controller handler =
|
Object handler = handlerMappings.stream()
|
||||||
requestMappingHandlerMapping.findHandler(new HandlerKey(RequestMethod.valueOf(req.getMethod()), req.getRequestURI()));
|
.filter(hm -> hm.findHandler(new HandlerKey(requestMethod, requestURI)) != null)
|
||||||
|
.map(hm -> hm.findHandler(new HandlerKey(requestMethod, requestURI)))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new ServletException("No handler for [" + requestMethod + ", " + requestURI + "]"));
|
||||||
|
|
||||||
if (handler == null) {
|
if (handler == null) {
|
||||||
resp.sendError(404);
|
resp.sendError(404);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.example.mvc;
|
||||||
|
|
||||||
|
import org.example.mvc.controller.HandlerKey;
|
||||||
|
|
||||||
|
public interface HandlerMapping {
|
||||||
|
Object findHandler(HandlerKey handlerKey);
|
||||||
|
}
|
||||||
@@ -5,12 +5,12 @@ import org.example.mvc.controller.*;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class RequestMappingHandlerMapping {
|
public class RequestMappingHandlerMapping implements HandlerMapping {
|
||||||
|
|
||||||
private Map<HandlerKey, Controller> mappings = new HashMap<>();
|
private Map<HandlerKey, Controller> mappings = new HashMap<>();
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
mappings.put(new HandlerKey(RequestMethod.GET, "/"), new HomeController());
|
// mappings.put(new HandlerKey(RequestMethod.GET, "/"), new HomeController());
|
||||||
mappings.put(new HandlerKey(RequestMethod.GET, "/users"), new UserListController());
|
mappings.put(new HandlerKey(RequestMethod.GET, "/users"), new UserListController());
|
||||||
mappings.put(new HandlerKey(RequestMethod.POST, "/users"), new UserCreateController());
|
mappings.put(new HandlerKey(RequestMethod.POST, "/users"), new UserCreateController());
|
||||||
mappings.put(new HandlerKey(RequestMethod.GET, "/user/form"), new ForwardController("/user/form"));
|
mappings.put(new HandlerKey(RequestMethod.GET, "/user/form"), new ForwardController("/user/form"));
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import org.example.mvc.view.ModelAndView;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public class SimpleControllerHandlerAdaptor implements HandlerAdapter {
|
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Object handler) {
|
public boolean supports(Object handler) {
|
||||||
return (handler instanceof Controller);
|
return (handler instanceof Controller);
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.example.mvc.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Controller {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.example.mvc.annotation;
|
||||||
|
|
||||||
|
import org.example.mvc.controller.RequestMethod;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface RequestMapping {
|
||||||
|
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
RequestMethod[] method() default {};
|
||||||
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
package org.example.mvc.controller;
|
package org.example.mvc.controller;
|
||||||
|
|
||||||
|
import org.example.mvc.annotation.Controller;
|
||||||
|
import org.example.mvc.annotation.RequestMapping;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public class HomeController implements Controller{
|
@Controller
|
||||||
@Override
|
public class HomeController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/",method = RequestMethod.GET)
|
||||||
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
return "home.jsp";
|
return "home";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user