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,会 ...
随机推荐
- elasticsearch 占CPU过高
一.线上有一台服务器cpu一直跑满,最终定位导是elasticsearch导致的 二.通过一波查找更改jvm和删除 修改后没有生效笔记尴尬 然后网友说删除索引试了试就可以了 哈哈 curl http ...
- 排列组合python
python 的 itertools模块 可以专业的处理的排列组合问题 写在自己博客里,怕下次找不到喽
- 关于分布式环境下的id生成
public class IdWorker { //基准时间 public const long Twepoch = 1288834974657L; //机器标识位数 ; //数据标志位数 ; //序 ...
- [复试机试]c++读取/写入文本文件
读取文件 #include <iostream> #include <cstdio> #include <string> #include <cstdlib& ...
- Portainer介绍
Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台操作.Swarm集群和服 ...
- 【安富莱原创开源应用第1期】花式玩转网络摄像头之TCP上位机软件实现,高端大气上档次,速度2MB/S,华丽丽的界面效果
说明:1.例子是两年前做的,一直没有顾上整理出来,今天特地整理出来,开源出来给大家玩.2.上位机是emWin模拟器开发的,大家估计很难猜到,所以你会emWin话的,就可以轻松制作上位机.做些通信和控制 ...
- 最快效率求出乱序数组中第k小的数
题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k 的元素值 思路:这里很容易想到直接排序然后顺序查找,可以使用效率较高的快排,但是它的时间复杂度是O(nlgn),我们这里可以用一种简便的方法,不 ...
- #Java学习之路——基础阶段(第七篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- [Swift]LeetCode269. 外星人词典 $ Alien Dictionary
There is a new alien language which uses the latin alphabet. However, the order among letters are un ...
- [Swift]LeetCode925. 长按键入 | Long Pressed Name
Your friend is typing his name into a keyboard. Sometimes, when typing a character c, the key might ...