Javaweb——BaseServlet 缺乏、安全感 2021-06-15 20:36 362阅读 0赞 # BaseServlet # ## 1.作用 ## 我们知道,写一个项目可能会出现很多个Servlet,而且一般一个Servlet只有一个方法(doGet或doPost),如果项目大一些,那么Servlet的数量就会很惊人。 为了避免Servlet的“膨胀”,我们写一个BaseServlet。它的作用是让一个Servlet可以处理多种不同的请求。不同的请求调用Servlet的不同方法。我们写好了BaseServlet后,让其他Servlet继承BaseServlet,例如CustomerServlet继承BaseServlet,然后在CustomerServlet中提供add()、update()、delete()等方法,每个方法对应不同的请求。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1NjUxMjc_size_16_color_FFFFFF_t_70] ## 2.分析 ## 我们知道,Servlet中处理请求的方法是service()方法,这说明我们需要让service()方法去调用其他方法。例如调用add()、mod()、del()、all()等方法!具体调用哪个方法需要在请求中给出方法名称!然后service()方法通过方法名称来调用指定的方法。 无论是点击超链接,还是提交表单,请求中必须要有method参数,这个参数的值就是要请求的方法名称,这样BaseServlet的service()才能通过方法名称来调用目标方法。例如某个链接如下:`<a href=”/xxx/CustomerServlet?method=add”>添加客户</a>` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1NjUxMjc_size_16_color_FFFFFF_t_70 1] ## 3.代码 ## 初步代码: public class AServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 获取参数,用来识别用户想请求的方法 */ String methodName = request.getParameter("method"); if (methodName.equals("addUser")) { addUser(request, response); } else if (methodName.equals("editUser")) { editUser(request, response); } else if (methodName.equals("deleteUser")) { deleteUser(request, response); } } public void addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("add"); } public void editUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("edit"); } public void deleteUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("delete"); } } 但是这里有个问题,就是这些代码的扩展性很差,也没法重用,我们在其他的servlet中没法使用,而且如果我们添加新的方法还要对上面的代码进行修改。这个时候我们就思考,能不能得到方法的名称,然后使用反射来调用方法。最后,我们把它变成抽象类,写成BaseServlet,这样以后再写有多个方法的servlet时继承它就可以了! public abstract class BaseServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 获取参数,用来识别用户想请求的方法 */ String methodName = request.getParameter("method"); /* * 判断是否有method参数 */ if (methodName == null || methodName.trim().isEmpty()) { throw new RuntimeException("没有传递method参数!"); } /* * 得到方法名称,使用反射来调用方法。 得到方法名,通过方法名再得到Method类的对象。 需要得到Class,然后在调用它的方法进行查询。 * 得到Method 我们需要查询的是当前类的方法,所以我们需要先得到当前类的Class。 */ Class c = this.getClass();// 得到当前类的Class对象 Method method = null; try { // 得到当前的方法 method = c.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); } catch (Exception e) { throw new RuntimeException("调用的方法" + methodName + "()不存在!"); } try { method.invoke(this, request, response); } catch (Exception e) { System.out.println("你调用的方法内部出现异常!"); throw new RuntimeException(e); } } } 这个时候,我们再思考一下,我们在得到请求之后,经常需要进行转发和重定向。我们可以在处理的方法的方法体中写转发和重定向操作,但是这样有些繁琐。这个时候,我们决定: 调用的方法返回值类型我们设为String,执行完方法之后,我们要返回一个字符串,来显示我们的意图,转发或者重定向或者不进行操作。 例如: public String addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("add"); return "f:/index.jsp"; } 然后,我们再对BaseServlet进行修改,使得它能够处理我们的请求。 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.equals("r")) { // 重定向 response.sendRedirect(request.getContextPath() + path); } else if (s.equals("f")) { // 转发 request.getRequestDispatcher(path).forward(request, response); } else { // 不是r也不是f throw new RuntimeException("你指定的操作当前版本不支持!"); } } else { // 没有冒号。默认为转发。 request.getRequestDispatcher(result).forward(request, response); } } catch (Exception e) { System.out.println("你调用的方法内部出现异常!"); throw new RuntimeException(e); } -------------------- END. [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1NjUxMjc_size_16_color_FFFFFF_t_70]: /images/20210615/8a4bc3b0874f4d81a7638fae919d9002.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1NjUxMjc_size_16_color_FFFFFF_t_70 1]: /images/20210615/7a13e3a9d9d2460998ef6d8ccd25050f.png
还没有评论,来说两句吧...