标签:contain 结构 路径 not 基础 res font containe ack
Web框架
一. 前言
在前上一章教程中,我们实现了程序在Tomcat上的部署。
本章将在上一章的基础上,进一步扩展程序。
注:
1.本文针对初学Java的同学训练学习思路,请不要太纠结于细节问题。
2.本文旨在达到抛砖引玉的效果,希望大家扩展本例子,以学到更多知识的精髓。
学习本章需要准备的知识:
1.读完本系列教程的前面章节。
2.理解Java注解
二. 步入正题
话不多说,大家自己理解,下面步入正题:
我们来做一个简单的Web框架如下:
修改前:
修改后:
工程结构如下:
我们希望用一个普通的Java类而不是Servlet来处理Web请求,
比如如下的代码:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Controller // 用@Controller注解表示这个类可以处理web请求 7 public class PersonController { 8 9 @Request(path="/person.do") // 请求路径 10 public String query(@Parameter(name="personid")String personId) { //参数名 11 12 MyContainer container = MyContainer.getInstance(); 13 PersonService personService = (PersonService)container.getObject(PersonService.class); 14 15 Person personResult = personService.getPerson(personId); 16 17 StringBuffer result = new StringBuffer(); 18 result.append("id:"+personResult.id); 19 result.append("<br/>username:"+personResult.username); 20 result.append("<br/>password:"+personResult.passwd); 21 22 return result.toString(); 23 } 24 25 }
引用的注解定义如下:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Target(value = { ElementType.TYPE }) 7 @Retention(value = RetentionPolicy.RUNTIME) 8 public @interface Controller { 9 10 }
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Target(value = { ElementType.PARAMETER }) 7 @Retention(value = RetentionPolicy.RUNTIME) 8 public @interface Parameter { 9 10 String name(); 11 12 }
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 @Target(value = { ElementType.METHOD }) 7 @Retention(value = RetentionPolicy.RUNTIME) 8 public @interface Request { 9 10 String path(); 11 12 }
要把请求分发到这个普通的Java类上,我们需要在框架层处理这个映射:
首先,我们把所有的请求都放到一个Servlet中,然后通过这个Servlet来根据请求的路径,去调用具体的业务逻辑方法。
修改web.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>fileview_web05</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>dispacherServlet</servlet-name> <servlet-class>vip.java123.fileview.fw.web.DispacherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispacherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
然后做一个DispacherServlet来做请求分发:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 public class DispacherServlet extends HttpServlet{ 7 8 private Map<String,ControllerInvoker> controllerMap = new HashMap<String,ControllerInvoker>(); 9 10 public DispacherServlet() { 11 // load all controller 12 String controllerPackage = "vip.java123.fileview.app.web"; 13 14 try { 15 // 扫描controller包下面的所有类,并加载包含注解@Controller的类 16 Class[] controllerClasses = ClassScaner.getClasses(controllerPackage); 17 for(int i = 0; i < controllerClasses.length; i ++) { 18 Class controller = controllerClasses[i]; 19 20 // 判断是否含有注解@Controller 21 if(controller.getAnnotation(Controller.class) != null) { 22 23 // 生成新的Controller实例 24 Object obj = controller.newInstance(); 25 26 // 扫描所有的方法 27 Method[] methods = controller.getMethods(); 28 for(int j = 0; j < methods.length; j ++) { 29 Method method = methods[j]; 30 31 // 加载含有@Request注解的方法 32 Request requestAnnotation = method.getAnnotation(Request.class); 33 if(requestAnnotation != null) { 34 35 // 注解声明的请求路径 36 String path = requestAnnotation.path(); 37 38 // 做一个invoker,以便请求过来时调用 39 ControllerInvoker invoker = new ControllerInvoker(); 40 invoker.path = path; 41 invoker.obj = obj; 42 invoker.method = method; 43 44 // 处理@Parameter注解 45 List<String> parameterNameList = new ArrayList<String>(); 46 Annotation[][] annotations = method.getParameterAnnotations(); 47 for(int k = 0; k < annotations.length; k ++) { 48 if(annotations[k].length > 0) { 49 Parameter parameterAnnotaion = (Parameter)annotations[k][0]; 50 String parameterName = parameterAnnotaion.name(); 51 parameterNameList.add(parameterName); 52 } 53 } 54 invoker.paramNames = new String[parameterNameList.size()]; 55 for(int m = 0; m < parameterNameList.size(); m ++) { 56 invoker.paramNames[m] = parameterNameList.get(m); 57 } 58 59 // 将做好的invoker放入Map中,key为请求路径 60 System.out.println("load controller:"+path); 61 controllerMap.put(path, invoker); 62 } 63 } 64 } 65 } 66 67 } catch (ClassNotFoundException e) { 68 e.printStackTrace(); 69 } catch (IOException e) { 70 e.printStackTrace(); 71 } catch (InstantiationException e) { 72 e.printStackTrace(); 73 } catch (IllegalAccessException e) { 74 e.printStackTrace(); 75 } 76 77 } 78 79 /** 80 * 处理Get请求 81 */ 82 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 83 // 获得请求路径 84 String contextPath = request.getContextPath(); 85 String requestPath = request.getRequestURI(); 86 String path = requestPath.replace(contextPath, ""); 87 88 System.out.println("request:"+path); 89 90 // 根据请求路径获得做好的invoker 91 ControllerInvoker invoker = controllerMap.get(path); 92 93 if(invoker != null) { 94 // 根据请求的参数值设置invoker 95 invoker.paramValues = new String[invoker.paramNames.length]; 96 for(int i = 0; i < invoker.paramNames.length; i ++) { 97 invoker.paramValues[i] = request.getParameter(invoker.paramNames[i]); 98 } 99 100 // 调用invoker,并将结果写到response中 101 String result = invoker.invokMethod(); 102 response.getWriter().println(result); 103 } 104 } 105 106 }
需要一个辅助类ControllerInvoker来支持:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 public class ControllerInvoker { 7 8 public String path; 9 public Object obj; 10 public Method method; 11 public String[] paramNames; 12 public String[] paramValues; 13 14 // 调用制定的方法 15 public String invokMethod() { 16 try { 17 return (String)method.invoke(obj, paramValues); 18 } catch (IllegalArgumentException e) { 19 e.printStackTrace(); 20 } catch (IllegalAccessException e) { 21 e.printStackTrace(); 22 } catch (InvocationTargetException e) { 23 e.printStackTrace(); 24 } 25 26 return null; 27 } 28 }
三. 测试
启动服务器:
向服务器请求person.html文件,在浏览器端输入1,点query按钮:
显示查询结果:
完整程序请大家从[这里]下载
如有问题,大家来我的网站进行提问。
https://www.java123.vip/qa
版权声明:本教程版权归java123.vip所有,禁止任何形式的转载与引用。
标签:contain 结构 路径 not 基础 res font containe ack
原文地址:https://www.cnblogs.com/java123-vip/p/9771083.html