模仿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. Excel大批量数据导出

    package com.tebon.ams.util; import lombok.extern.slf4j.Slf4j;import org.apache.poi.openxml4j.excepti ...

  2. proxy_pass根据path路径转发时的"/"问题记录

    在nginx中配置proxy_pass时,如果是按照^~匹配路径时,要注意proxy_pass后的url最后的/.当加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理 ...

  3. #Java学习之路——第一部分总结

    今天主要是Java的入门以及idea的安装说实话,没有什么有技术含量的东西,发的也全是皮毛,但是在数组部分有很多细节需要注意,在JDK环境变量配置的地方不光光只有windows 的环境配置,还要掌握补 ...

  4. Java常用工具类练习题

    1.请根据控制台输入的特定日期格式拆分日期 如:请输入一个日期(格式如:**月**日****年) 经过处理得到:****年**月**日 提示:使用String的方法indexOf.lastIndexO ...

  5. Oracle视图(和Mysq一样l)

    本章内容: Oracle视图介绍与创建.Oracle视图的查询与修改.Oracle的复杂视图 1. Oracle视图介绍与创建 (1)了解常见的数据库对象都有哪些 (2)了解什么是视图以及为什么要使用 ...

  6. 6.Git基础-远程仓库的使用

    远程仓库是指托管在因特网或其他网络中的你的项目的版本库.比如你在GitHub中托管的代码库,就是远程仓库. 1.查看远程仓库 --  git remote  git remote 查看已经配置的远程仓 ...

  7. python编译、运行、反编译pyc文件

    为了加密 .py 文件,以前一般使用打包成 exe ,但是最近发现可以将其编译成二进制文件 pyc ,虽然反编译难度不大,但是也需要一些水平 编译生成 pyc: 单个文件 代码: import py_ ...

  8. scala合并Array

    val newarray = Array(1,2,3)++Array(4,5) newarray.foreach(println) 打印结果: 1 2 3 4 5

  9. Python内置函数(8)——bytes

    英文文档: class bytes([source[, encoding[, errors]]]) Return a new “bytes” object, which is an immutable ...

  10. 【快速入门ORM框架之Dapper】大牛勿进系列

    前言:dapper是什么?Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的.也就是说实体类都要自己写.它没有复杂 ...