@Controller @RequestMapping
<dependencies> <!--servlet依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--各种工具--> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.5</version> </dependency> </dependencies> 复制代码
@ExtController
和 @ExtRequestMapping
,定义一个自己的Controller 注解如下
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ExtController { } 复制代码
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ExtRequestMapping { String value() default ""; } 复制代码
自己定义的controller如下
@ExtController @ExtRequestMapping("/") public class IndexController { @ExtRequestMapping public String getIndex() { System.out.println("自定义的MVC框架"); return "index"; } } 复制代码
由于是个Web项目,我们在Web.xml里面配置好自己的DispatcherServlet的映射
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>disaptcher</servlet-name> <servlet-class>com.libi.mvc.servlet.ExtDispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>disaptcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 复制代码
/**mvc的Bean容器,存入Controller对象*/ private ConcurrentHashMap<String, Object> controllerBeans = new ConcurrentHashMap<String, Object>(); /**mvc的请求地址,把Url和Controller建立映射*/ private ConcurrentHashMap<String, Object> urlBeans = new ConcurrentHashMap<String, Object>(); /**mvc的请求方法名称,把Url和方法名建立映射*/ private ConcurrentHashMap<String, Object> urlMethods = new ConcurrentHashMap<String, Object>(); 复制代码
@ExtController
注解的类,实例化后放在mvc的bean容器里 public void init() throws ServletException { //扫描Controller包下面的类,并且找到所有带@Controller的注解倒到Bean容器里 List<Class<?>> classes = ClassUtils.getClasses("com.controller"); try { findClassMvcAnnoation(classes); } catch (Exception e) { e.printStackTrace(); } } /**找到带有Controller注解的类然后初始化放入bean容器里*/ private void findClassMvcAnnoation(List<Class<?>> classes) throws IllegalAccessException, InstantiationException { for (Class<?> classInfo : classes) { ExtController extController = classInfo.getAnnotation(ExtController.class); if (extController != null) { String beanId = ClassUtils.toLowerCaseFirstOne(classInfo.getSimpleName()); mvcBeans.put(beanId, classInfo.newInstance()); } } } 复制代码
/**将URL映射和方法关联起来*/ private void handleMapping() { //遍历Controller,判断类上是否有RequestMapping注解 for (Map.Entry<String, Object> entry : controllerBeans.entrySet()) { Object controller = entry.getValue(); //判断类是否加上了@RequestMapping注解 Class<?> classInfo = controller.getClass(); ExtRequestMapping classRequestMapping = classInfo.getDeclaredAnnotation(ExtRequestMapping.class); String baseUrl = ""; if (classRequestMapping != null) { //获取Url映射的地址 baseUrl = classRequestMapping.value(); } //判断方法上是否加上了RequestMapping Method[] methods = classInfo.getDeclaredMethods(); for (Method method : methods) { //获取方法上的映射 ExtRequestMapping methodRequestMapping = method.getDeclaredAnnotation(ExtRequestMapping.class); if (methodRequestMapping != null) { String methodUrl = baseUrl + methodRequestMapping.value(); //装入映射表 System.out.println("put url:"+methodUrl); urlBeans.put(methodUrl, controller); urlMethods.put(methodUrl, method); } } } } 复制代码
上面这一步在init()方法里,创建完controller实例之后执行
/**处理请求*/ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求url地址 String url = req.getRequestURI(); System.out.println("url:"+url); //从map集合中获取controller Object controller = urlBeans.get(url); if (controller == null) { //到这里说明页面不存在 resp.getWriter().println("404 not find url"); return; } //从map中获取方法,调用并且获取返回结果 Method method = urlMethods.get(url); if (method == null) { //到这里说明页面不存在 resp.getWriter().println("404 not find method"); return; } String result = (String) methodInvoke(method, controller); resp.getWriter().println(result); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } private Object methodInvoke(Method method, Object controller) { Object result = null; try { result = method.invoke(controller); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } return result; } 复制代码
写到这里的效果如下
/**视图解析器*/ private void extResourceViewResolver(String pageName, HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { String prefix = "/WEB-INF/view/"; String suffix = ".jsp"; request.getRequestDispatcher(prefix+pageName+suffix).forward(request,response); } 复制代码
以上代码在doGet里执行
/**处理请求*/ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求url地址 String url = req.getRequestURI(); System.out.println("url:"+url); //从map集合中获取controller Object controller = urlBeans.get(url); if (controller == null) { //到这里说明页面不存在 resp.getWriter().println("404 not find url"); return; } //从map中获取方法,调用并且获取返回结果 Method method = urlMethods.get(url); if (method == null) { //到这里说明页面不存在 resp.getWriter().println("404 not find method"); return; } String result = (String) methodInvoke(method, controller); //-----------------使用视图转换器渲染页面 extResourceViewResolver(result,req,resp); //------------------ } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } 复制代码
/WEB-INF/view/index.jsp内容如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>index</title> </head> <body> <h1>自己手写mvc——index.jsp</h1> </body> </html> 复制代码
执行后效果如下