BaseServlet
1.让Servlet中有多个请求处理方法
1).我们希望在一个Servlet中可以有多个请求处理方法!
domain:User
dao:UserDao
service:UserService
servlet:UserServlet
void init(ServletConfig config)
void destory()
void service(ServletRequest, ServletResponse)throws IOException,ServletException{
在这里让它调用其他方法!
要求:用户发出请求时,必须给出一个参数,来说明要调用哪一个方法
//获取参数,通过参数名称来确定要调用的方法
}
public void addUser(){
}
http://localhost:8080/xxx/AServlet?m=addUser
2).客户端发送请求时,必须多给出一个参数,用来说明要调用的方法
请求处理方法的签名必须和service相同(类型doGet和doPost结构和service相同,由service调用),即返回值和参数,以及声明的异常都相同!
3).客户端必须传递名为method的参数!
package com.xjs.servlet; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.management.RuntimeErrorException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 在这里给出多个请求处理方法 请求处理方法:除了名称以外,都与service方法相同! * @author hp */ public class AServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.获取参数,用来识别用户想请求的方法 * 2.然后判断是哪一个方法,是哪一个我们就调用哪一个方法 */ String methodName = request.getParameter("method"); if(methodName == null || methodName.trim().isEmpty()){ throw new RuntimeException("您没有传递method参数!无法确定您想调用的方法。"); } /* * 得到方法名称,是否可通过反射来调用方法? * 1.得到方法名,通过方法名在得到Method类的对象! * >需要得到Class,然后调用它的方法进行查询!得到Method * >我们要查询的是当前类的方法,所以我们需要得到当前类的Class */ Class c=this.getClass();//得到当前类的class对象 //查询方法-->参数:1.方法名 2.两个需要用到的对象的类 Method method = null; try { method=c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);//方法名,参数 } catch (Exception e) { throw new RuntimeException("您要调用的方法:"+methodName+",它不存在。"); } /* * 反射调用 * 调用method表示的方法--参数 */ try { method.invoke(this, request,response); } catch (Exception e) { System.out.println("您调用的方法:"+methodName+",它内部抛出了异常!"); throw new RuntimeException(e);//继续向外抛,让用户看到抛出的异常 } /*//这段代码不可重用。每增加一个方法,这里就需要判断一下 if(method.equals("addUser")){ addUser(request,response); }else if(method.equals("editUser")){ editUser(request,response); }else if(method.equals("deleteUser")){ deleteUser(request, response); }*/ } public void addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("addUser..."); throw new RuntimeException("测试一下"); } public void editUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("editUser..."); } public void deleteUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("deleteUser..."); } public void selectUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("selectUser..."); } }
把上边的代码封装到一个类中
BaseServlet.java:--> 一个继承HttpServlet的抽象类(Class不是Servlet),不需要再web.xml中配置。
package com.xjs.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 abstract class BaseServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.获取参数,用来识别用户想请求的方法 * 2.然后判断是哪一个方法,是哪一个我们就调用哪一个方法 */ String methodName = request.getParameter("method"); if(methodName == null || methodName.trim().isEmpty()){ throw new RuntimeException("您没有传递method参数!无法确定您想调用的方法。"); } /* * 得到方法名称,是否可通过反射来调用方法? * 1.得到方法名,通过方法名在得到Method类的对象! * >需要得到Class,然后调用它的方法进行查询!得到Method * >我们要查询的是当前类的方法,所以我们需要得到当前类的Class */ Class c=this.getClass();//得到当前类的class对象 //查询方法-->参数:1.方法名 2.两个需要用到的对象的类 Method method = null; try { method=c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);//方法名,参数 } catch (Exception e) { throw new RuntimeException("您要调用的方法:"+methodName+",它不存在。"); } /* * 反射调用 * 调用method表示的方法--参数 */ try { method.invoke(this, request,response); } catch (Exception e) { System.out.println("您调用的方法:"+methodName+",它内部抛出了异常!"); throw new RuntimeException(e);//继续向外抛,让用户看到抛出的异常 } /*//这段代码不可重用。每增加一个方法,这里就需要判断一下 if(method.equals("addUser")){ addUser(request,response); }else if(method.equals("editUser")){ editUser(request,response); }else if(method.equals("deleteUser")){ deleteUser(request, response); }*/ } }
AServlet.java:--->直接继承BaseServlet就可以实现一个Servlet中有多个请求处理方法。
package com.xjs.servlet; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.management.RuntimeErrorException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 在这里给出多个请求处理方法 请求处理方法:除了名称以外,都与service方法相同! * @author hp */ public class AServlet extends BaseServlet{ public void addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("addUser..."); throw new RuntimeException("测试一下"); } public void editUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("editUser..."); } public void deleteUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("deleteUser..."); } public void selectUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("selectUser..."); } }
2.让Servlet完成转发或者重定向(在1的基础上改)
BaseServlet.java:
package com.xjs.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 abstract class BaseServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.获取参数,用来识别用户想请求的方法 * 2.然后判断是哪一个方法,是哪一个我们就调用哪一个方法 */ String methodName = request.getParameter("method"); if(methodName == null || methodName.trim().isEmpty()){ throw new RuntimeException("您没有传递method参数!无法确定您想调用的方法。"); } /* * 得到方法名称,是否可通过反射来调用方法? * 1.得到方法名,通过方法名在得到Method类的对象! * >需要得到Class,然后调用它的方法进行查询!得到Method * >我们要查询的是当前类的方法,所以我们需要得到当前类的Class */ Class c=this.getClass();//得到当前类的class对象 //查询方法-->参数:1.方法名 2.两个需要用到的对象的类 Method method = null; try { method=c.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);//方法名,参数 } catch (Exception e) { throw new RuntimeException("您要调用的方法:"+methodName+",它不存在。"); } /* * 反射调用 * 调用method表示的方法--参数 */ try { String result = (String)method.invoke(this, request,response); /* * 获取请求处理方法执行后返回的字符串,它表示转发或者重定向的路径! * 帮它完成转发或者重定向! */ //如果用户返回的字符串为null,或为"",那么我们什么也不做! if(result == null || result.trim().isEmpty()){ return;//方法结束 } /* * 查看返回字符串中是否包含冒号,如果没有,表示转发 * 如果有,使用冒号分割字符串,得到前缀和后缀! * 其中前缀如果是f,表示转发,如果是r表示重定向,后缀就是要转发或重定向的路径 */ if(result.contains(":")){ //使用冒号分割字符串,得到前缀和后缀 int index=result.indexOf(":");//获取冒号的位置 String s = result.substring(0, index);//截取前缀 String path = result.substring(index+1);//截取后缀 if(s.equalsIgnoreCase("r")){//前缀r,重定向 response.sendRedirect(request.getContextPath()+path); }else if(s.equalsIgnoreCase("f")){//前缀f,转发 request.getRequestDispatcher(path).forward(request, response); }else{ throw new RuntimeException("你指定的操作:"+s+",当前版本不支持!"); } }else{//没有冒号,默认为转发! request.getRequestDispatcher(result).forward(request, response); } } catch (Exception e) { System.out.println("您调用的方法:"+methodName+",它内部抛出了异常!"); throw new RuntimeException(e);//继续向外抛,让用户看到抛出的异常 } /*//这段代码不可重用。每增加一个方法,这里就需要判断一下 if(method.equals("addUser")){ addUser(request,response); }else if(method.equals("editUser")){ editUser(request,response); }else if(method.equals("deleteUser")){ deleteUser(request, response); }*/ } }
只需自己写的Servlet(在这是BServlet)继承BaseServlet就行(则子类就有多个处理方法,以及转发和重定向的功能了)。
BServlet.java:
package com.xjs.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BServlet extends BaseServlet { public String fun1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("fun1()..."); return "/index.jsp"; } public String fun2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("fun2()..."); return "r:/index.jsp"; } public String fun3(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("fun3()..."); return null; } }
转发和重定向实现的原理:在Servlet中的某方法执行完之后,会返回一个字符串,根据所得的字符串进行截取、判断,然后完成相应的转发或者重定向。