web实训项目(快递e栈)-----02编写mvc框架

项目结构:

 DispatcherServlet.java

 1 package com.zzk.mvc;
 2 
 3 import javax.servlet.ServletConfig;
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 import java.lang.reflect.InvocationTargetException;
11 import java.lang.reflect.Method;
12 
13 /**
14  * @Author: zzk
15  * @Description:
16  * @Date Created in 2021-04-10-16:48
17  * @Modified By:
18  */
19 public class DispatcherServlet extends HttpServlet {
20     @Override
21     public void init(ServletConfig config) throws ServletException {
22         //获取连接名称
23         //得到映射路径 path    application.properties
24         String path = config.getInitParameter("contentConfigLocation");
25         //获取资源通道
26         //获取映射路径的资源输入流 getResourceAsStream(path)    is
27         InputStream is = DispatcherServlet.class.getClassLoader().getResourceAsStream(path);
28         //获取资源
29         //需要一个映射器来加载相应关联的方法
30         HandlerMapping.load(is);
31     }
32 
33     @Override
34     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
35         //1.    获取用户请求的uri
36         String uri = req.getRequestURI();
37         HandlerMapping.MVCMapping mapping = HandlerMapping.get(uri);
38         if (mapping == null){
39             resp.sendError(404,"自定义MVC:映射地址不存在"+uri);
40             return;
41         }
42         Object obj = mapping.getObj();
43         Method method = mapping.getMethod();
44         Object result = null;
45         try {
46             result = method.invoke(obj, req, resp);
47         } catch (IllegalAccessException e) {
48             e.printStackTrace();
49         } catch (InvocationTargetException e) {
50             e.printStackTrace();
51         }
52         switch (mapping.getType()){
53             case TEXT:
54                 resp.getWriter().write((String)result);
55                 break;
56             case VIEW:
57                 resp.sendRedirect((String)result);
58                 break;
59         }
60     }
61 }

HandlerMapping.java

  1 package com.zzk.mvc;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.lang.annotation.Annotation;
  6 import java.lang.reflect.Method;
  7 import java.util.Collection;
  8 import java.util.HashMap;
  9 import java.util.Map;
 10 import java.util.Properties;
 11 
 12 /**
 13  *  映射器(包含了大量的网址与方法的对应关系)
 14  */
 15 public class HandlerMapping {
 16     private static Map<String,MVCMapping> data = new HashMap<>();
 17 
 18     public static MVCMapping get(String uri){
 19         return data.get(uri);
 20     }
 21 
 22     public static void load(InputStream is){
 23         Properties ppt = new Properties();
 24         try {
 25             ppt.load(is);       //load方法将配置文件application.properties中的键值对存到了Properties类型的ppt中
 26         } catch (IOException e) {
 27             e.printStackTrace();
 28         }
 29         //获取配置文件中描述的一个个类(键值对的右半边value,不包括左半边key)
 30         Collection<Object> values = ppt.values();
 31         //for循环,每次是一个类被加载
 32         for (Object cla:values) {
 33             //将类的名称强转为字符串,com.xxx.demo1
 34             String className = (String) cla;
 35             try {
 36                 //加载配置文件中描述的每一个类
 37                 //将字符串类型加载为一个类,c:com.xxx.demo1
 38                 Class c = Class.forName(className);
 39                 //通过这个类的无参构造方法来创建这个类的对象-------------------对象
 40                 Object obj = c.getConstructor().newInstance();
 41                 //获取这个类的所有方法-------------------------------------方法
 42                 Method[] methods = c.getMethods();
 43                 //遍历每一个方法(登录,注册,管理员相关操作),通过注解的方式给方法分类,进行判断
 44                 for (Method m:methods) {
 45                     //注解as
 46                     Annotation[] as = m.getAnnotations();
 47                     if (as != null){
 48                         //遍历这个方法的所有注解
 49                         for (Annotation annotation:as) {
 50                             if (annotation instanceof ResponseBody){
 51                                 //说明此方法,用于返回字符串给客户端
 52                                 MVCMapping mapping = new MVCMapping(obj,m,ResponseType.TEXT);
 53                                 Object o = data.put(((ResponseBody) annotation).value(),mapping);
 54                                 if (o != null){
 55                                     //存在了重复的请求地址
 56                                     throw new RuntimeException("请求地址重复:"+((ResponseBody) annotation).value());
 57                                 }
 58                             }else if (annotation instanceof ResponseView){
 59                                 //说明此方法,用于返回界面给客户端
 60                                 MVCMapping mapping = new MVCMapping(obj,m,ResponseType.VIEW);
 61                                 Object o = data.put(((ResponseView) annotation).value(),mapping);
 62                                 if (o != null){
 63                                     //存在了重复的请求地址
 64                                     throw new RuntimeException("请求地址重复:"+((ResponseView) annotation).value());
 65                                 }
 66                             }
 67                         }
 68                     }
 69                 }
 70             } catch (Exception e) {
 71                 e.printStackTrace();
 72             }
 73         }
 74     }
 75     /**
 76      *  映射对象,每一个对象封装了一个方法,用于处理请求
 77      */
 78     public static class MVCMapping{
 79         private Object obj;
 80         private Method method;
 81         private ResponseType type;
 82 
 83         public MVCMapping() {
 84         }
 85 
 86         public MVCMapping(Object obj, Method method, ResponseType type) {
 87             this.obj = obj;
 88             this.method = method;
 89             this.type = type;
 90         }
 91 
 92         public Object getObj() {
 93             return obj;
 94         }
 95 
 96         public void setObj(Object obj) {
 97             this.obj = obj;
 98         }
 99 
100         public Method getMethod() {
101             return method;
102         }
103 
104         public void setMethod(Method method) {
105             this.method = method;
106         }
107 
108         public ResponseType getType() {
109             return type;
110         }
111 
112         public void setType(ResponseType type) {
113             this.type = type;
114         }
115     }
116 }

ResponseType.java

 1 package com.zzk.mvc;
 2 
 3 /**
 4  * @Author: zzk
 5  * @Description:
 6  * @Date Created in 2021-04-10-18:29
 7  * @Modified By:
 8  */
 9 public enum ResponseType {
10     TEXT,VIEW;
11 }

ResponseBody.java

 1 package com.zzk.mvc;
 2 
 3 import java.lang.annotation.*;
 4 
 5 /**
 6  * 注解的作用:
 7  *  被此注解添加的方法,  会被用于处理请求
 8  *  方法返回的内容,    会以文字形式返回到客户端
 9  */
10 @Target(ElementType.METHOD)
11 @Retention(RetentionPolicy.RUNTIME)
12 @Documented
13 public @interface ResponseBody {
14     String value();
15 }

ResponseView.java

 1 package com.zzk.mvc;
 2 
 3 import java.lang.annotation.*;
 4 
 5 /**
 6  * 注解的作用:
 7  *  被此注解添加的方法,  会被用于处理请求
 8  *  方法返回的内容,    会直接重定向
 9  */
10 @Target(ElementType.METHOD)
11 @Retention(RetentionPolicy.RUNTIME)
12 @Documented
13 public @interface ResponseView {
14     String value();
15 }

application.properties

 1 #在这里配置每一个用于处理请求的类,每一个类中可能包含0-n个用于处理请求的方法
 2 #用于管理员的controller
 3 admin=com.zzk.controller.AdminController
 4 #用于快递管理的controller
 5 express=com.zzk.controller.ExpressController
 6 #用于快递员管理的controller
 7 courier=com.zzk.controller.CourierController
 8 #用于用户管理的controller
 9 user=com.zzk.controller.UserController
10 
11 #微信端用于用户管理的controller
12 wechatUser=com.zzk.wx.controller.UserController
13 #微信端用于快递管理的controller
14 wechatExpress=com.zzk.wx.controller.ExpressController
15 #微信端用于二维码管理的controller
16 wechatQRCode=com.zzk.wx.controller.QRCodeController

web.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6     <servlet>
 7         <servlet-name>DispatcherServlet</servlet-name>
 8         <servlet-class>com.zzk.mvc.DispatcherServlet</servlet-class>
 9         <init-param>
10             <param-name>contentConfigLocation</param-name>
11             <param-value>application.properties</param-value>
12         </init-param>
13         <load-on-startup>0</load-on-startup>
14     </servlet>
15     <servlet-mapping>
16         <servlet-name>DispatcherServlet</servlet-name>
17         <url-pattern>*.do</url-pattern>
18     </servlet-mapping>
19 </web-app>
原文地址:https://www.cnblogs.com/zhangzhongkun/p/14750088.html