#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;
|
||||
|
||||
import org.example.mvc.controller.Controller;
|
||||
import org.example.mvc.controller.HandlerKey;
|
||||
import org.example.mvc.controller.RequestMethod;
|
||||
import org.example.mvc.view.JspViewResolver;
|
||||
@@ -10,7 +9,6 @@ import org.example.mvc.view.ViewResolver;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
@@ -18,7 +16,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@WebServlet("/")
|
||||
@@ -26,16 +23,27 @@ public class DispatcherServlet extends HttpServlet {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DispatcherServlet.class);
|
||||
|
||||
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||
private List<HandlerMapping> handlerMappings;
|
||||
private List<ViewResolver> viewResolvers;
|
||||
private List<HandlerAdapter> handlerAdapters;
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
requestMappingHandlerMapping = new RequestMappingHandlerMapping();
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -43,9 +51,15 @@ public class DispatcherServlet extends HttpServlet {
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
log.info("[DispatcherServlet] service started.");
|
||||
|
||||
String requestURI = req.getRequestURI();
|
||||
RequestMethod requestMethod = RequestMethod.valueOf(req.getMethod());
|
||||
|
||||
try {
|
||||
Controller handler =
|
||||
requestMappingHandlerMapping.findHandler(new HandlerKey(RequestMethod.valueOf(req.getMethod()), req.getRequestURI()));
|
||||
Object handler = handlerMappings.stream()
|
||||
.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) {
|
||||
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.Map;
|
||||
|
||||
public class RequestMappingHandlerMapping {
|
||||
public class RequestMappingHandlerMapping implements HandlerMapping {
|
||||
|
||||
private Map<HandlerKey, Controller> mappings = new HashMap<>();
|
||||
|
||||
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.POST, "/users"), new UserCreateController());
|
||||
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.HttpServletResponse;
|
||||
|
||||
public class SimpleControllerHandlerAdaptor implements HandlerAdapter {
|
||||
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
|
||||
@Override
|
||||
public boolean supports(Object handler) {
|
||||
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;
|
||||
|
||||
import org.example.mvc.annotation.Controller;
|
||||
import org.example.mvc.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class HomeController implements Controller{
|
||||
@Override
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@RequestMapping(value = "/",method = RequestMethod.GET)
|
||||
public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
return "home.jsp";
|
||||
return "home";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user