BaseServlet类的介绍
结合代码分析--BaseServlet存在的意义(刚接触servlet的必看)
看到一个jsp/servlet实现MVC模式的项目中使用了BaseServlet,一开始并不理解这个类的作用,感觉是多此一举,但看了几篇文章后才发现原来是自己写的代码太low了,学识尚浅理解不了。但大牛总是从菜鸟走过来的嘛,虚心学习总没错。 故将自己的理解分享在博客上。
介绍
BaseServlet并不是什么很高大上的东西,它只是一个普通的、继承了HttpServlet类并重写了其中service方法的类。
使用方式
继承该类
存在的意义
对于刚刚接触编程的人来说,如果刚学完servlet,写一个增删改查的demo一般都会分别写四个servlet类,分别对应四种操作,就像这样:AddServlet
DeleteServlet
UpdateServlet
QueryServlet
,但这样不仅代码冗余的非常厉害,而且还需要对每个servlet一一配置,(特别是servlet3.0以前需要在web.xml中配置,会非常麻烦,web.xml文件也会变得很大,若修改配置很难找到对应)。相应的整个项目也会显得很大,为了解决这种问题就有了改进的版本。
--------------------------------------- 分割线 ---------------------------------------------------
一些已经接触编程一段时间的人会将增删改查四个操作写在一个servlet中,调用某个方法的时候只需要在servlet映射的url后面添加参数,比如:<a
href="/testServlet?method=add">添加</a>
,然后在servlet中添加if判断method参数的值来调用不同的方法,类似这样:
-
String method = request.getParameter("method");
-
if(method.equals("add")) {
-
add(...); //省略参数 下同
-
} else if(method.equals("update")) {
-
delete();
-
} else if(method.equals("query")) {
-
update(...);
-
} else{
-
query(...);
-
}
-
这确实是个不错的办法(因为我在学习BaseServlet之前用的就是这种方式 哈哈哈),但我现在可以理解为:编写这段代码的人很有想法,但编程水平还仅仅在初级阶段。因为他只考虑到完成了增删改查的功能,并没有考虑到对功能的扩展。如果增加一个功能(假设一个功能对应一个方法),他要修改一次if语句的判断,那如果增加一百个功能呢?难道要改一百次代码?更何况有时候项目已经上线,难道要用户自己修改? 这还仅仅是一个servlet,对应一个domain类的操作,稍微大一点的项目至少就有一二十个domain类吧(我也没接触过,猜的,但绝对不会少),每个servlet都有着那么多操作,那要写多少if语句判断啊。
--------------------------------------- 分割线 ---------------------------------------------------
所以BaseServlet就应运而生了,它作为一个项目中所有servlet的基类,(个人感觉该类属于设计模式中的前端控制器,类似SpringMVC的DispatcherServlet),其中并没有任何的业务逻辑,只负责将请求处理后分发到不同的servlet进行不同的处理。
下面就结合代码理解一下该类(因为BaseServlet类只重写了service方法所以我只贴出service方法的代码,而且代码可能与你网上找到的有些细节方面不太相同,但基本原理是一样的),我会将解释写在代码的注释里:
-
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
//下面这个if语句可以不用看,这里用到了我项目中另一个类:GetRequest,该类继承了HttpRequestWrapper,将request进行了包装,主要是防止乱码
-
if(((HttpServletRequest)request).getMethod().equalsIgnoreCase("get")) {
-
if(!(request instanceof GetRequest)) {
-
request = new GetRequest((HttpServletRequest)request);
-
}
-
} else {
-
((HttpServletRequest)request).setCharacterEncoding("utf-8");
-
}
-
-
//设置response的返回数据格式以及字符编码
-
response.setContentType("text/html;charset=UTF-8");
-
//在这里获取前台传来的method参数
-
String methodName = ((HttpServletRequest)request).getParameter("method");
-
/*
-
* Method类,是java反射机制使用到的一个类
-
* API对该类的解释是:提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
-
* 看到这里是不是有点清楚BaseServlet是怎么调用方法的了?
-
* 这里先定义了一个Method的引用,遵循编写代码的规范原则,在try-catch外定义引用,块内实现
-
*/
-
Method method = null;
-
-
try {
-
/* 这行代码的意思是实例化一个以methodName命名,以HttpServletRequest对象和HttpServletResponse对象做参数的方法
-
* 大家都知道this指的是调用当前方法的类的对象
-
* 所以不要想当然的认为this指的是BaseServlet对象,而是继承自BaseServlet的、与你请求的url相匹配的Servlet
-
* 这个Servlet当然由你自己实现
-
*/
-
method = this.getClass().getMethod(methodName, new Class[]{HttpServletRequest.class, HttpServletResponse.class});
-
} catch (Exception var10) {
-
//你自定义的servlet中没有对应的方法时,处理异常。
-
throw new RuntimeException("您要调用的方法:" + methodName + "它不存在!", var10);
-
}
-
-
try {
-
//这行代码表示调用了刚才实例化的Method对象所对应的方法,并用e接收方法的返回值
-
String e = (String)method.invoke(this, new Object[]{request, response});
-
//对e进行一些必要的判断
-
if(e != null && !e.trim().isEmpty()) {
-
/* 这里需要解释一下返回字符串的构成
-
* 可以直接返回要跳转的视图名,这样将会跳转到对应视图
-
* 若返回视图名的字符串前指定了转发的方式,如:f:list.jsp 或 r:list.jsp
-
* 那么下面语句会判断使用何种方式转发视图
-
*/
-
int index = e.indexOf(":");
-
if(index == -1) {
-
//没有指定视图的转发方式 ((HttpServletRequest)request).getRequestDispatcher(e).forward((ServletRequest)request, response);
-
} else {
-
String start = e.substring(0, index);
-
String path = e.substring(index + 1);
-
if(start.equals("f")) {
-
//如果指定了f,则使用forward方式跳转 ((HttpServletRequest)request).getRequestDispatcher(path).forward((ServletRequest)request, response);
-
} else if(start.equals("r")) {
-
//如果指定了r,则使用redirect方式重定向 response.sendRedirect(((HttpServletRequest)request).getContextPath() + path);
-
}
-
}
-
}
-
-
} catch (Exception var9) {
-
throw new RuntimeException(var9);
-
}
-
}
代码的执行流程如上。总结一下:
该方法中使用了反射机制来调用方法,不论你的Servlet中有多少方法,这段代码都不需要改变,只需要你提供方法名和参数列表就可以完成调用。若有别的domain类添加,只需要将对应的Servlet继承该类即可,不需要额外的代码。 继承后你只需要关心自己的逻辑即可,不用关心怎样被调用。
以上就是我对BaseServlet的理解,如有不同见解希望能一起讨论,如果写的有错欢迎指正
上一篇: JavaWeb-XML-学习笔记