封装Servlet工具类
一.封装过程
1.1 封装前
1.1.1为何要封装Servlet
- 在编写Servlet程序时我们发现,为了对应前端jsp不同的功能,我们需要相应的创建的多个Servlet:
- 登录功能:LoginServlet
- 注册功能:RegisterServlet
- 增加功能:AddServlet
- 注销功能:LogoutServlet
.....
- 如果如上创建多个Servlet,不仅导致整个项目Servlet过多,名称难起,代码重复过多,所以我们考虑对应一个整体模块使用一个Servlet,通过判断不同的功能跳转到不同方法中去实现
- 在编写Servlet程序时我们发现,为了对应前端jsp不同的功能,我们需要相应的创建的多个Servlet:
- 登录功能:LoginServlet
- 注册功能:RegisterServlet
- 增加功能:AddServlet
- 注销功能:LogoutServlet
- 如果如上创建多个Servlet,不仅导致整个项目Servlet过多,名称难起,代码重复过多,所以我们考虑对应一个整体模块使用一个Servlet,通过判断不同的功能跳转到不同方法中去实现
1.2 版本1:通过if判断方法实现
1.2.1代码实现
package it.cn.store.user.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class UserServlet
*/
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据,封装实体
String methodName = request.getParameter("methodName");
if("register".equalsIgnoreCase(methodName)){
register(request,response);
}else if ("login".equalsIgnoreCase(methodName)) {
login(request,response);
}else if ("logout".equalsIgnoreCase(methodName)) {
logout(request,response);
}else {
System.out.println("未知错误,系统即将自爆!!!!!");
}
//调用Service对象,操作
//数据回显
}
//注销
public void logout(HttpServletRequest request, HttpServletResponse response) {
System.out.println("执行注销操作,全体都有");
}
//登录
public void login(HttpServletRequest request, HttpServletResponse response) {
System.out.println("登录程序准备启动,一级准备");
}
//注册
public void register(HttpServletRequest request, HttpServletResponse response) {
System.out.println("注册程序开始启动,请准备好~~~~爆炸~~");
}
}
package it.cn.store.user.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class UserServlet
*/
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据,封装实体
String methodName = request.getParameter("methodName");
if("register".equalsIgnoreCase(methodName)){
register(request,response);
}else if ("login".equalsIgnoreCase(methodName)) {
login(request,response);
}else if ("logout".equalsIgnoreCase(methodName)) {
logout(request,response);
}else {
System.out.println("未知错误,系统即将自爆!!!!!");
}
//调用Service对象,操作
//数据回显
}
//注销
public void logout(HttpServletRequest request, HttpServletResponse response) {
System.out.println("执行注销操作,全体都有");
}
//登录
public void login(HttpServletRequest request, HttpServletResponse response) {
System.out.println("登录程序准备启动,一级准备");
}
//注册
public void register(HttpServletRequest request, HttpServletResponse response) {
System.out.println("注册程序开始启动,请准备好~~~~爆炸~~");
}
}
1.2.2思路分析
- 创建不同功能对应的不同方法
- 获取用户前端输入方法名称methodName
- 根据方法名进行if判断
- 测试结果
- - - - - - - - - - - - - - - - - - - - - - - - - - -
1.2.3细节分析
- 功能实现:
- 通过if判断实现不同的mentodName调用不同的方法
- 优缺点:
- 优点:实现了一个Servlet中多个功能
- 缺点:扩展性差:每次添加一个功能,就要一个if去对应
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1.3 版本2:通过反射调用实现
1.3.1代码实现
package it.cn.store.user.web.servlet;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
为了提高扩展性,通过反射调用
*/
public class UserServletDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据,封装实体
String methodName = request.getParameter("methodName");
//1.获取当前类的全类名---获取这个类
Class clazz = this.getClass();
try {
//2.反射获得方法
Method method = clazz.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
//3.反射调用
method.invoke(this, request,response);
} catch (Exception e) {
e.printStackTrace();
}
//调用Service对象,操作
//数据回显
}
//注销
public void logout(HttpServletRequest request, HttpServletResponse response) {
System.out.println("执行注销操作,全体都有");
}
//登录
public void login(HttpServletRequest request, HttpServletResponse response) {
System.out.println("登录程序准备启动,一级准备");
}
//注册
public void register(HttpServletRequest request, HttpServletResponse response) {
System.out.println("注册程序开始启动,请准备好~~~~爆炸~~");
}
}
1.3.2思路分析
- 根据不同功能创建不同方法
- 获取用户前端输入方法名称methodName
- 获取当前类的全类名
- 根据methodName获取反射
- 反射调用实现功能
- 测试调用
1.3.3细节分析
- 功能实现:
- 通过反射的方式实现功能选择
- 优缺点:
- 优点:通过反射调用,会根据传入的方法名自动调用响应的方法,提高扩展性
- 缺点:
- 反射等内容还是存放在Servlet中,对于整个Servlet体系没有通用性
- 要进行回显等操作,还会存在return遗漏等问题,程序设计不够优化
- 编写注意事项:
- 通过反射获得方法中,两个参数:
- 第一个:methodName,传入需要调用的方法名(举例:login)
- 第二个:paramClass,传入参数类型的.class形式(举例:HttpServletRequest.class)
- 反射调用方法:
- 第一个:方法所在对象:本例中:this,代表当前类
- 第二个:与反射定义方法中class类对应的对象
- 反射调用中规定:
- clazz.getMethod() //仅获得被public修饰方法
- clazz.getDeclaredMethods() //可以反射获得所有权限修饰符的方法(public protected default private)
- 通过反射获得方法中,两个参数:
1.4 版本3:通过抽取工具类实现
1.4.1代码实现
- 工具类:BasicServlet
package it.cn.store.user.utils;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BasicServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
/**
* 重写HttpServlet中重载的Servlet方法
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据,封装实体
String methodName = request.getParameter("methodName");
//1.获取当前类的全类名---获取这个类
Class clazz = this.getClass();
try {
//2.反射获得方法
Method method = clazz.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
//3.反射调用
String path = (String) method.invoke(this, request,response);
//信息回显
if(path!=null && !"".equals(path)){
//程序员想要请求转发
request.getRequestDispatcher(path).forward(request, response);
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 原始Servlet extends BasicSerlvet
package it.cn.store.user.web.servlet;
import java.io.IOException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import it.cn.store.user.utils.BasicServlet;
/**
为了提高扩展性,通过反射调用
*/
public class UserServletDemo1 extends BasicServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收数据,封装实体
//调用Service对象,操作
//数据回显
}
//注销
public void logout(HttpServletRequest request, HttpServletResponse response) {
System.out.println("执行注销操作,全体都有");
}
//登录
public void login(HttpServletRequest request, HttpServletResponse response) {
System.out.println("登录程序准备启动,一级准备");
}
//注册
public void register(HttpServletRequest request, HttpServletResponse response) {
System.out.println("注册程序开始启动,请准备好~~~~爆炸~~");
}
}
1.4.2思路分析
- BasicServlet
1.编写BasicServlet继承HttpServlet
2.
重写HttpServlet中service重载方法
(在Servlet生命周期中Service()一直运行)
- 为什么重写service重载方法:
- 因为重载方法已经将service中原本ServletRequest和ServletResponse参数转换成了HttpServletRequest和ServletResponse
- 重写service不就不会判断父类中service对应的get和post请求了:
- 已经不需要在意是get和post方法了
4.回显数据(莫忘return)
- Servlet
2.加入空参构造(也可以不写,系统默认添加)
2.在Servlet只要关注(编写)功能即可
1.4.3实现过程
1.浏览器输入网址,向服务器发出请求
2.服务器接收请求,进行url-pattern匹配,先匹配Filter,再匹配servlet
3.匹配到相应的MyServlet,调用MyServlet中service方法
- 发现原始Servlet中没有执行service()方法,去父类中找
- 在BasicServlet没有执行service()方法,还是要去父类中找(有重写,但是没有执行)
- 父类HttpServlet 中的service方法执行,把request和response对象进行强转,调用重载的service方法。this.service(request,response)
- 由于调用Mysevlet中service方法,所以该this代表Myservlet,所以要找Myservlet中是否重写servcie方法,发现Myservlet中没重写,去父类中找
- 发现BasicServlet中重写了,就执行其中代码
4.执行service()中反射部分,invoke(this,request,response)对应功能方法methodName
- 理解invoke中this,由于我们调用时候Myservlet所以该this代表就是Myservlet
6.获取返回值并进行回显操作
1.4.4细节分析
- 功能实现:
- 通过抽取工具类重写service方法+反射实现功能选择
- 优缺点:
- 优点:
- 抽取工具类,通用性和维护性提高
- 通过反射调用,会根据传入的方法名自动调用响应的方法,提高扩展性
- 在servlet中只要关注功能编写,结构太美!
- 缺点:
- 暂无
- 优点:
- 编写注意事项:
- 在BasicServlet中重写service()方法是根据servlet生命周期每次调用都会执行service()方法
- 可以都不用写空参构造,系统会自动添加,这样就会寻找父类
- 但是不能写了空参构造,不写super(),那就没法寻找父类了