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,会 ...
随机推荐
- Multi-Get API
multiGet API并行地在单个http请求中执行多个get请求. Multi-Get Request MultiGetRequest构造函数为空,需要你添加`MultiGetRequest.It ...
- lua语言自学知识点----简单了解
零碎知识点: lua:用lua写UI,更新UI,因为lua可直接跨平台解析,不需要编译,方便更新------>热更新. c#反射也可以达到更新,但非常麻烦,切不支持iOS. 在lua中一个人汉字 ...
- Docker常用命令(一)
[转]原始出处:http://zxx287856774.blog.51cto.com/3417296/1665264 docker中 启动所有的容器命令 docker start $(docker p ...
- JSP的执行原理
在一个JSP文件第一次被请求时,JSP引擎把该JSP文件转换成为一个Servlet.而这个引擎本身也是一个Servlet.JSP的运行过程如下所示: (1)JSP引擎先把该JSP文件转换成一个Java ...
- 分享我在 vue 项目中关于 api 请求的一些实现及项目框架
本文主要简单分享以下四点 如何使用 axios 如何隔离配置 如何模拟数据 分享自己的项目框架 本文主要目的为以下三点 希望能够帮到一些人 希望能够得到一些建议 奉上一个使用Vue的模板框架 我只是把 ...
- HBase之Table.put客户端流程
首先,让我们从HTable.put方法开始.由于这一节有很多方法只是简单的参数传递,我就简单略过,但是,关键的方法我还是会截图讲解,所以希望大家尽可能对照源码进行流程分析.另外,在这一节,我单单介绍p ...
- 【JVM虚拟机】(2)---GC 算法与种类
GC 算法与种类 对于垃圾收集(GC), 我们需要考虑三件事情:哪些内存需要回收?如何判断是垃圾对象?垃圾回收算法有哪些? 一.GC的工作区域 1.不是GC的工作区域 (1)程序计数器.虚拟机栈和本地 ...
- .net core 2.0 Code First Fluent API配置
A.net core 2.0新特性支持通过IEntityTypeConfiguration<>添加Code First配置到一个封装类. 新建目标框架为.NET Core类库 新建完了以后 ...
- Android Studio代码行数统计插件Statistics
Android Studio 是没有提提供统计代码全部行数的功能的,但是对于开发者来说,这个功能确实必备的,Statistic统计代码行数非常方便,也很详细. 1,首先肯定是将插件下载下来,下载地址: ...
- 计蒜客:Entertainment Box
Ada, Bertrand and Charles often argue over which TV shows to watch, and to avoid some of their fight ...