数据增删改查: 需要用5个Servlet(crud)其中修改要用两个serclet,一个是查询的servlet,一个是修改的servlet。在项目实际开发中,一个模块至少要写5个servlet,如果有多个模块,是不是要写更多的servlet,造成代码冗余。
思考:如何减少Servlet数量
原理:
从客户端向服务端发起请求,每次都要传递额外的键值对的数据method=””,
服务端获取到method对应的内容之后,通过判断不同的内容调用不同的功能
从客户端向服务端发起请求,调用功能方式:
1_通过表单向服务端发起请求
2_通过链接向服务端发起请求
3_Ajax向服务端发起请求
以下做了一个简单的页面,包含了三种方式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
</head>
<body>
<form action="/BaseServlet/ServletDemo01?method=addStu" method="post">
用户<input type="text" name="username"/><br/>
<button>提交</button>
</form>
<br/>
<a href="/BaseServlet/ServletDemo01?method=delStu">删除学生</a><br/>
<button onclick="fn()">按钮</button>
<script type="text/javascript">
function fn() {
$.post("/BaseServlet/ServletDemo01",{"method":"checkStu","user":"tom"},function(data) {
alert(data);
})
}
</script>
</body>
</html>
接下来应该写Servlet,代码如下:
package cn.itcast.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String md=request.getParameter("method");
if("addStu".equals(md)) {
System.out.println("添加学生");
}else if("delStu".equals(md)) {
System.out.println("删除学生");
}else if("checkStu".equals(md)) {
System.out.println("查询该学生是否存在");
}else if("".equals(md)) {
}
}
}
只是简单的进行了以下处理,看看是否能正确调用。接下来对代码进行升级,第2版代码如下
public class ServletDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String md=request.getParameter("method");
String path=null;
if("addStu".equals(md)) {
addStu(request,response);
}else if("delStu".equals(md)) {
delStu(request,response);
}else if("checkStu".equals(md)) {
checkStu(request,response);
}else if("".equals(md)) {
}
}
protected void addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
}
protected void delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
}
protected void checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("查询该学生是否存在");
}
}
想了一下,发现不管是添加还是删除学生,最后都要返回全查的页面,以便看看是否执行成功,代码继续升级:
package cn.itcast.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取客户端提交到服务端的method对应的值
String md=request.getParameter("method");
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
//通过判断md中不同的内容来决定本次功能
if("addStu".equals(md)){
path=addStu(request, response);
}else if("delStu".equals(md)){
path=delStu(request, response);
}else if("checkStu".equals(md)){
path=checkStu(request, response);
}else if("".equals(md)){
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
}
protected String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
return "/test.html";
}
protected String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
return "/test.html";
}
protected String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("检查学生");
response.getWriter().println("DDDDDD");
return null;
}
}
在这里要说明一下checkStu方法,它本身是无需返回页面,在这里仍然把它的返回类型设置为String,直接仍然让其返回null
①PrintWriter out=response.getWriter();
out对象用于输出字符流数据
好了,看到这里,不知道大家有没有想过,如果doGet()方法里有许多if/else,这是应该怎么办?
在解决这个问题之前,我们先了解一下反射的用途,直接上一个简单的代码,新建一个类AA
package cn.itcast.servlet;
public class AA {
public int sum(int a,int b){
System.out.println("AAAAA......2");
return a+b;
}
public int sum(int a,int b,int c){
return a+b+c;
}
}
再来个测试类TestAA:
package cn.itcast.servlet;
import java.lang.reflect.Method;
public class TestAA {
public static void main(String[] args) throws Exception {
//获取到AA字节码在内存中对象
Class clazz=AA.class;
//获取AA字节码对象上名称为sum的方法,参数有2个参数(第一个参数代表方法的名称,第二个参数parameterTypes是按声明顺序标识该方法形参类型)
Method md = clazz.getMethod("sum", int.class,int.class);
//Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,
//如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,
//如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,
//再将其返回
//执行md方法
md.invoke(new AA(), 123,4);
}
}
输出结果如下:
回到一开始的问题,使用反射技术来代替过多的if/else,代码如下:
package cn.itcast.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 ServletDemo02 extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取客户端提交到服务端的method对应的值
String md=request.getParameter("method");
//定义变量,存放功能执行完毕之后要转发的路径
String path=null;
//获取到当前字节码对象(ServletDemo02.class在内存中对象)
Class clazz = this.getClass();
try {
//获取clazz上名称为md方法
Method method=clazz.getMethod(md, HttpServletRequest.class,HttpServletResponse.class);
if(null!=method){
//调用找到的方法
path=(String)method.invoke(this, request,response);
}
if(null!=path){
//服务端的转发
request.getRequestDispatcher(path).forward(request, response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String addStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("添加学生");
return "/test.html";
}
public String delStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("删除学生");
return "/test.html";
}
public String checkStu(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("检查学生");
response.getWriter().println("DDDDDD");
return null;
}
}
写到这,不知道有没有小伙伴发现,ServletDemo02中的代码除了代替if/else那段代码外,还将所有的访问修饰符全部替换为public,这是为什么了?(解释:
)如果仍然是protected,又会报什么错?getMethod
只能调用public声明的方法,而getDeclaredMethod基本可以调用任何类型声明的方法
如果是protected,会报java.lang.NoSuchMethodException异常,详见:https://blog.youkuaiyun.com/love_moon821/article/details/78077972