模仿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 + 封装表单参数的更多相关文章

  1. httpclient模拟post请求json封装表单数据

    好长时间不更博了,主要肚子里没什么好墨水,哈哈.废话不说上代码. public static String httpPostWithJSON(String url) throws Exception ...

  2. struts2(二) 表单参数自动封装和参数类型自动转换

    前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...

  3. struts2(三)之表单参数自动封装与参数类型自动转换

    前言 对struts2的使用不外乎这几点,参数自动封装,拦截器的使用,数据校验,ognl表达(值栈和actionContext的讲解),struts2的标签,struts2的国际化, struts2的 ...

  4. 框架学习之Struts2(二)---基本配置和封装表单数据

    一.结果页面配置 1.局部结果页面配置 <!-- 局部结果页面配置--> <package name = "demo" extends = "strut ...

  5. Struts2学习(二)———— 表单参数自动封装和参数类型自动转换

    前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...

  6. 利用BeanUtils工具类封装表单数据

    一.BeanUtils工具类的使用 1.首先导入BeanUtils工具类的jar包 commons-beanutils-1.8.0.jar commons-logging-1.1.1.jar 2.se ...

  7. 什么是请求参数、表单参数、url参数、header参数、Cookie参数?一文讲懂

    最近在工作中对 http 的请求参数解析有了进一步的认识,写个小短文记录一下. 回顾下自己的情况,大概就是:有点点网络及编程基础,只需要加深一点点对 HTTP 协议的理解就能弄明白了. 先分享一个小故 ...

  8. Golang里实现Http服务器并解析header参数和表单参数

    在http服务里,header参数和表单参数是经常使用到的,本文主要是练习在Go语言里,如何解析Http请求的header里的参数和表单参数,具体代码如下: package server import ...

  9. 统一修改表单参数(表单提交的空字符串统一转null)

    统一修改表单参数(表单提交的空字符串统一转null) 1.介绍: 我们业务中有时会遇到提交的表单中某个参数为空字符串,导致后台接受的为空字符串("")而不是我们理想中的null,会 ...

随机推荐

  1. Multi-Get API

    multiGet API并行地在单个http请求中执行多个get请求. Multi-Get Request MultiGetRequest构造函数为空,需要你添加`MultiGetRequest.It ...

  2. lua语言自学知识点----简单了解

    零碎知识点: lua:用lua写UI,更新UI,因为lua可直接跨平台解析,不需要编译,方便更新------>热更新. c#反射也可以达到更新,但非常麻烦,切不支持iOS. 在lua中一个人汉字 ...

  3. Docker常用命令(一)

    [转]原始出处:http://zxx287856774.blog.51cto.com/3417296/1665264 docker中 启动所有的容器命令 docker start $(docker p ...

  4. JSP的执行原理

    在一个JSP文件第一次被请求时,JSP引擎把该JSP文件转换成为一个Servlet.而这个引擎本身也是一个Servlet.JSP的运行过程如下所示: (1)JSP引擎先把该JSP文件转换成一个Java ...

  5. 分享我在 vue 项目中关于 api 请求的一些实现及项目框架

    本文主要简单分享以下四点 如何使用 axios 如何隔离配置 如何模拟数据 分享自己的项目框架 本文主要目的为以下三点 希望能够帮到一些人 希望能够得到一些建议 奉上一个使用Vue的模板框架 我只是把 ...

  6. HBase之Table.put客户端流程

    首先,让我们从HTable.put方法开始.由于这一节有很多方法只是简单的参数传递,我就简单略过,但是,关键的方法我还是会截图讲解,所以希望大家尽可能对照源码进行流程分析.另外,在这一节,我单单介绍p ...

  7. 【JVM虚拟机】(2)---GC 算法与种类

    GC 算法与种类 对于垃圾收集(GC), 我们需要考虑三件事情:哪些内存需要回收?如何判断是垃圾对象?垃圾回收算法有哪些? 一.GC的工作区域 1.不是GC的工作区域 (1)程序计数器.虚拟机栈和本地 ...

  8. .net core 2.0 Code First Fluent API配置

    A.net core 2.0新特性支持通过IEntityTypeConfiguration<>添加Code First配置到一个封装类. 新建目标框架为.NET Core类库 新建完了以后 ...

  9. Android Studio代码行数统计插件Statistics

    Android Studio 是没有提提供统计代码全部行数的功能的,但是对于开发者来说,这个功能确实必备的,Statistic统计代码行数非常方便,也很详细. 1,首先肯定是将插件下载下来,下载地址: ...

  10. 计蒜客:Entertainment Box

    Ada, Bertrand and Charles often argue over which TV shows to watch, and to avoid some of their fight ...