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>
分类:
230515 / Javaweb
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
2019-05-10 冲刺第五天