JavaWeb - 模仿SpringMVC抽取 BaseServlet + 封装表单参数
模仿SpringMVC抽取一个BaseServlet,接收所有请求,然后自动封装表单参数和分发到对应的servlet执行,下面用一个页面表单提交,转发显示的项目做示例。
1)首先准备一个Entity,用来封装表单提交的参数
package com.qf.entity;
public class User {
private String name;
private String password;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", age=" + age + "]";
}
}
User.java
2)前端表单
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="UserServlet?action=addUser" method="post">
姓名:<input type="text" name="name" /><br>
密码:<input type="text" name="password" /><br>
年龄:<input type="text" name="age" /><br>
<input type="submit" value="添加" /><br>
</form>
</body>
</html>
index.jsp
3)抽取BaseServlet,不需要再web.xml中注册,但要继承HttpServlet;主要通过反射来实现,具体的步骤已在代码中注释
package com.qf.servlet; import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class BaseServlet extends HttpServlet {
private static final long serialVersionUID = 1L; public BaseServlet() {
} protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
if (action != null && !"".equals(action)) {
Class<?> clazz = this.getClass(); // 获取当前执行的servlet的反射对象
Method[] methods = clazz.getDeclaredMethods(); // 获取反射对象的所有方法
for (Method method : methods) {
if (action.equals(method.getName())) { // 查询action是否有对应的方法
InvokeMethod(method, request, response); // 调用执行匹配的method
break;
}
}
}
} /**
* 执行method和封装param
* @param method
* @param request
* @param response
*/
private void InvokeMethod(Method method, HttpServletRequest request, HttpServletResponse response) {
try {
Object[] paramIns = packageParam(method, request, response); // 封装method的形参
String invoke = (String) method.invoke(this, paramIns); // 调用对应方法执行,就收返回结果
responseClient(invoke, request, response); // 响应客户端
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} /**
* 封装method参数
* @param method
* @param request
* @param response
* @return
* @throws InstantiationException
*/
private Object[] packageParam(Method method, HttpServletRequest request, HttpServletResponse response) throws InstantiationException { Parameter[] parameters = method.getParameters(); // 获取method的所有参数
Object[] paramIns = new Object[parameters.length]; // 创建一个数组,用来保存处理后的参数 for (int i = 0; i < parameters.length; i++) { // 遍历参数
Class<?> paramObj = parameters[i].getType(); // 获取参数的Class
if ("HttpServletRequest".equals(paramObj.getSimpleName())) { // 处理 HttpServletRequest 参数
paramIns[i] = request;
} else if ("HttpServletResponse".equals(paramObj.getSimpleName())) { // 处理 HttpServletResponse 参数
paramIns[i] = response;
} else {
Object instance = null;
try {
instance = paramObj.newInstance(); // 实例化paramObj
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
Field[] fields = paramObj.getDeclaredFields(); // 获取paramObj所有的属性
try {
for (Field field : fields) { // 遍历属性
field.setAccessible(true); // 私有属性授权
String fieldName = field.getName(); // 获取属性名称
String value = request.getParameter(fieldName); // 根据属性名称从request中获取对应的值
Object val = null;
if (value != null && !"".equals(value)) {
val = changeParamType(value, field.getType()); // 把值类型转变为对应属性的类型
field.set(instance, val); // 把值赋给paramObj实例的对应属性
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
paramIns[i] = instance; // 保存参数
}
}
return paramIns;
} /**
* 表单数据类型转换
* @param value
* @param type
* @return
*/
private Object changeParamType(String value, Class<?> type) {
Object val = null; String name = type.getSimpleName(); // 获取类型名称
if ("String".equals(name)) {
val = value;
} else if ("Integer".equals(name)) {
val = Integer.parseInt(value);
} // 如有其他类型数据,else if 添加即可
return val;
} /**
* 解析执行结果
* @param invoke
* @param request
* @param response
*/
private void responseClient(String invoke, HttpServletRequest request, HttpServletResponse response) {
String[] split = invoke.split(":");
try {
if ("forward".equals(split[0])) {
request.getRequestDispatcher(split[1]).forward(request, response);
} else if ("redirect".equals(split[0])) {
response.sendRedirect(split[1]);
}
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }
BaseServlet.java
4)新建一个class,命名为UserServlet,UserServlet不需要继承HttpServlet,直接继承BaseServlet就可以了,但是要再在web.xml中注册;UserServlet中直接定义方法即可,但是方法名称必须和前端调用的名称保持一致
package com.qf.servlet;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import com.qf.entity.User;
@SuppressWarnings("all")
public class UserServlet extends BaseServlet {
public String addUser(User user, HttpServletRequest request) throws IOException {
request.setAttribute("user", user);
return "forward:test.jsp";
}
}
UserServlet.java
5)编写一个test.jsp,接收响应
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h4>姓名:${user.name}</h4>
<h4>密码:${user.password}</h4>
<h4>年龄:${user.age}</h4>
</body>
</html>
test.jsp
6)验证
a) 启动tomcat,浏览器输入项目部署路径,进入index.jsp,填写数据,提交

b) test.jsp展示OK,抽取成功

7)第一次写博客,如有不正之处,还请指正,谢谢!
JavaWeb - 模仿SpringMVC抽取 BaseServlet + 封装表单参数的更多相关文章
- httpclient模拟post请求json封装表单数据
好长时间不更博了,主要肚子里没什么好墨水,哈哈.废话不说上代码. public static String httpPostWithJSON(String url) throws Exception ...
- struts2(二) 表单参数自动封装和参数类型自动转换
前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...
- struts2(三)之表单参数自动封装与参数类型自动转换
前言 对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签,struts2的国际化, struts2的 ...
- 框架学习之Struts2(二)---基本配置和封装表单数据
一.结果页面配置 1.局部结果页面配置 <!-- 局部结果页面配置--> <package name = "demo" extends = "strut ...
- Struts2学习(二)———— 表单参数自动封装和参数类型自动转换
前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...
- 利用BeanUtils工具类封装表单数据
一.BeanUtils工具类的使用 1.首先导入BeanUtils工具类的jar包 commons-beanutils-1.8.0.jar commons-logging-1.1.1.jar 2.se ...
- 什么是请求参数、表单参数、url参数、header参数、Cookie参数?一文讲懂
最近在工作中对 http 的请求参数解析有了进一步的认识,写个小短文记录一下. 回顾下自己的情况,大概就是:有点点网络及编程基础,只需要加深一点点对 HTTP 协议的理解就能弄明白了. 先分享一个小故 ...
- Golang里实现Http服务器并解析header参数和表单参数
在http服务里,header参数和表单参数是经常使用到的,本文主要是练习在Go语言里,如何解析Http请求的header里的参数和表单参数,具体代码如下: package server import ...
- 统一修改表单参数(表单提交的空字符串统一转null)
统一修改表单参数(表单提交的空字符串统一转null) 1.介绍: 我们业务中有时会遇到提交的表单中某个参数为空字符串,导致后台接受的为空字符串("")而不是我们理想中的null,会 ...
随机推荐
- 2018申请淘宝客AppKey
1.www.alimama.com 申请账号进入后2.进入我的联盟,按下面的步骤 完成以后等待网站审核. 3.审核完成后 按以下的图,申请进入开放平台或得appkey 4.最后就可以进入开放平台申请看 ...
- 深入理解Spring Redis的使用 (三)、使用RedisTemplate的操作类访问Redis
上一篇说了RedisTemplate对注解事务的支持,以及提供的序列化器. 事务需要开启enableTransactionSupport,然后使用@transactional注解,里面直接通过回调的c ...
- [Swift]LeetCode477. 汉明距离总和 | Total Hamming Distance
The Hamming distance between two integers is the number of positions at which the corresponding bits ...
- [Swift]LeetCode889. 根据前序和后序遍历构造二叉树 | Construct Binary Tree from Preorder and Postorder Traversal
Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...
- 前端(各种demo)一:css实现三角形,css实现梯形,pop弹层,css伪类before,after使用,svg使用(持续更新中)
各种demo: 1.css实现正方形 思路:width为0:height为0:使用boder-width为正方形的边长的一半,不占任何字节:border-style为固体:border-color为正 ...
- 『没有上司的舞会 树形DP』
树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...
- 从锅炉工到AI专家(6)
欠拟合和过拟合 几乎所有的复杂方程都存在结果跟预期差异的情况,越复杂的方程,这种情况就越严重.这里面通常都是算法造成的,当然也存在数据集的个体差异问题. 所以"欠拟合"和" ...
- 从锅炉工到AI专家(1)
序言 标题来自一个很著名的梗,起因是知乎上一个问题:<锅炉设计转行 AI,可行吗?>,后来就延展出了很多类似的问句,什么"快递转行AI可行吗?"."xxx转行 ...
- Linux环境下tomcat的安装与使用
1.tomcat安装 1.1.前提条件: 需要准备一台Linux机器,我选择的是Ubuntu18. Linux机器上已经安装了JDK,使用java -version命令查看是否安装. stephen@ ...
- SpringBoot上传文件到本服务器 目录与jar包同级
前言 看标题好像很简单的样子,但是针对使用jar包发布SpringBoot项目就不一样了. 当你使用tomcat发布项目的时候,上传文件存放会变得非常简单,因为你可以随意操作项目路径下的资源.但是当你 ...