JavaWeb - 模仿SpringMVC抽取 BaseServlet + 封装表单参数
模仿SpringMVC抽取一个BaseServlet,接收所有请求,然后自动封装表单参数和分发到对应的servlet执行,下面用一个页面表单提交,转发显示的项目做示例。
1)首先准备一个Entity,用来封装表单提交的参数
1 package com.qf.entity; 2 3 public class User { 4 5 private String name; 6 7 private String password; 8 9 private Integer age; 10 11 public Integer getAge() { 12 return age; 13 } 14 15 public void setAge(Integer age) { 16 this.age = age; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public String getPassword() { 28 return password; 29 } 30 31 public void setPassword(String password) { 32 this.password = password; 33 } 34 35 @Override 36 public String toString() { 37 return "User [name=" + name + ", password=" + password + ", age=" + age + "]"; 38 } 39 40 }
User.java
2)前端表单
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Insert title here</title> 9 </head> 10 <body> 11 <form action="UserServlet?action=addUser" method="post"> 12 姓名:<input type="text" name="name" /><br> 13 密码:<input type="text" name="password" /><br> 14 年龄:<input type="text" name="age" /><br> 15 <input type="submit" value="添加" /><br> 16 </form> 17 </body> 18 </html>
index.jsp
3)抽取BaseServlet,不需要再web.xml中注册,但要继承HttpServlet;主要通过反射来实现,具体的步骤已在代码中注释
1 package com.qf.servlet; 2 3 import java.io.IOException; 4 import java.lang.reflect.Field; 5 import java.lang.reflect.InvocationTargetException; 6 import java.lang.reflect.Method; 7 import java.lang.reflect.Parameter; 8 9 import javax.servlet.ServletException; 10 import javax.servlet.http.HttpServlet; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 public class BaseServlet extends HttpServlet { 15 private static final long serialVersionUID = 1L; 16 17 public BaseServlet() { 18 } 19 20 protected void doGet(HttpServletRequest request, HttpServletResponse response) 21 throws ServletException, IOException { 22 String action = request.getParameter("action"); 23 if (action != null && !"".equals(action)) { 24 Class<?> clazz = this.getClass(); // 获取当前执行的servlet的反射对象 25 Method[] methods = clazz.getDeclaredMethods(); // 获取反射对象的所有方法 26 for (Method method : methods) { 27 if (action.equals(method.getName())) { // 查询action是否有对应的方法 28 InvokeMethod(method, request, response); // 调用执行匹配的method 29 break; 30 } 31 } 32 } 33 } 34 35 /** 36 * 执行method和封装param 37 * @param method 38 * @param request 39 * @param response 40 */ 41 private void InvokeMethod(Method method, HttpServletRequest request, HttpServletResponse response) { 42 try { 43 Object[] paramIns = packageParam(method, request, response); // 封装method的形参 44 String invoke = (String) method.invoke(this, paramIns); // 调用对应方法执行,就收返回结果 45 responseClient(invoke, request, response); // 响应客户端 46 } catch (InstantiationException e) { 47 e.printStackTrace(); 48 } catch (IllegalAccessException e) { 49 e.printStackTrace(); 50 } catch (IllegalArgumentException e) { 51 e.printStackTrace(); 52 } catch (InvocationTargetException e) { 53 e.printStackTrace(); 54 } 55 } 56 57 /** 58 * 封装method参数 59 * @param method 60 * @param request 61 * @param response 62 * @return 63 * @throws InstantiationException 64 */ 65 private Object[] packageParam(Method method, HttpServletRequest request, HttpServletResponse response) throws InstantiationException { 66 67 Parameter[] parameters = method.getParameters(); // 获取method的所有参数 68 Object[] paramIns = new Object[parameters.length]; // 创建一个数组,用来保存处理后的参数 69 70 for (int i = 0; i < parameters.length; i++) { // 遍历参数 71 Class<?> paramObj = parameters[i].getType(); // 获取参数的Class 72 if ("HttpServletRequest".equals(paramObj.getSimpleName())) { // 处理 HttpServletRequest 参数 73 paramIns[i] = request; 74 } else if ("HttpServletResponse".equals(paramObj.getSimpleName())) { // 处理 HttpServletResponse 参数 75 paramIns[i] = response; 76 } else { 77 Object instance = null; 78 try { 79 instance = paramObj.newInstance(); // 实例化paramObj 80 } catch (IllegalAccessException e1) { 81 e1.printStackTrace(); 82 } 83 Field[] fields = paramObj.getDeclaredFields(); // 获取paramObj所有的属性 84 try { 85 for (Field field : fields) { // 遍历属性 86 field.setAccessible(true); // 私有属性授权 87 String fieldName = field.getName(); // 获取属性名称 88 String value = request.getParameter(fieldName); // 根据属性名称从request中获取对应的值 89 Object val = null; 90 if (value != null && !"".equals(value)) { 91 val = changeParamType(value, field.getType()); // 把值类型转变为对应属性的类型 92 field.set(instance, val); // 把值赋给paramObj实例的对应属性 93 } 94 } 95 } catch (IllegalAccessException e) { 96 e.printStackTrace(); 97 } 98 paramIns[i] = instance; // 保存参数 99 } 100 } 101 return paramIns; 102 } 103 104 /** 105 * 表单数据类型转换 106 * @param value 107 * @param type 108 * @return 109 */ 110 private Object changeParamType(String value, Class<?> type) { 111 Object val = null; 112 113 String name = type.getSimpleName(); // 获取类型名称 114 if ("String".equals(name)) { 115 val = value; 116 } else if ("Integer".equals(name)) { 117 val = Integer.parseInt(value); 118 } // 如有其他类型数据,else if 添加即可 119 return val; 120 } 121 122 /** 123 * 解析执行结果 124 * @param invoke 125 * @param request 126 * @param response 127 */ 128 private void responseClient(String invoke, HttpServletRequest request, HttpServletResponse response) { 129 String[] split = invoke.split(":"); 130 try { 131 if ("forward".equals(split[0])) { 132 request.getRequestDispatcher(split[1]).forward(request, response); 133 } else if ("redirect".equals(split[0])) { 134 response.sendRedirect(split[1]); 135 } 136 } catch (ServletException e) { 137 e.printStackTrace(); 138 } catch (IOException e) { 139 e.printStackTrace(); 140 } 141 } 142 143 protected void doPost(HttpServletRequest request, HttpServletResponse response) 144 throws ServletException, IOException { 145 doGet(request, response); 146 } 147 148 }
BaseServlet.java
4)新建一个class,命名为UserServlet,UserServlet不需要继承HttpServlet,直接继承BaseServlet就可以了,但是要再web.xml中注册;UserServlet中直接定义方法即可,但是方法名称必须和前端调用的名称保持一致
1 package com.qf.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 7 import com.qf.entity.User; 8 9 @SuppressWarnings("all") 10 public class UserServlet extends BaseServlet { 11 12 public String addUser(User user, HttpServletRequest request) throws IOException { 13 request.setAttribute("user", user); 14 return "forward:test.jsp"; 15 } 16 }
UserServlet.java
5)编写一个test.jsp,接收响应
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Insert title here</title> 9 </head> 10 <body> 11 <h4>姓名:${user.name}</h4> 12 <h4>密码:${user.password}</h4> 13 <h4>年龄:${user.age}</h4> 14 </body> 15 </html>
test.jsp
6)验证
a) 启动tomcat,浏览器方法项目部署路径,进入index.jsp,填写数据,提交
b) test.jsp展示OK,抽取成功
7)第一次写博客,如有不正之处,还请指正,谢谢!