美文网首页Java 杂谈
Servlet抽取技术简单案例

Servlet抽取技术简单案例

作者: SingleXu | 来源:发表于2018-12-03 11:32 被阅读2次

    在实际的开发中,我们经常会遇见一个业务逻辑下会有多个功能的情况,对应到java中也就是会产生多个Servlet.

    例如用户业务下就有登陆,注册,退出功能(如图1):

    image

    当Servlet过多对性能会产生影响,那么我们能不能把同一逻辑下的多个Servlet合为一个Servlet呢?

    对于这个问题的核心是一个Servlet如何判断出浏览器客户端的真实请求功能呢?这里我们可以通过请求传递参数来实现,服务器获取到请求的参数,通过判断参数来调用不同的方法来实现业务功能.

    注意:这里客户端必须与服务器端进行约定,我这里使用的是method代表功能.
    思想:如下图所示:

    image

    环境搭建:

    图片.png

    浏览器客户端代码我使用的是JSP文件

    客户端JSP代码:

    
    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <%--
        向服务器发送请求
        约定好键值对数据,告知服务器
        请求的功能是什么
    --%>
    <body>
         <a href="${pageContext.request.contextPath}/user?method=login">登陆</a><br>
        <a href="${pageContext.request.contextPath}/user?method=reg">注册</a><br>
        <a href="${pageContext.request.contextPath}/user?method=exit">退出</a>
    </body>
    </html>
    

    Java代码:

    package com.xfz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(urlPatterns = "/user")
    public class UserServlet extends HttpServlet {
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          /*
           * 获取提交的参数
           * 并判断内容调用方法
           * */
          String method = request.getParameter("method");
          if("login".equals(method)){
              login(request,response);
          }else if("reg".equals(method)){
              reg(request,response);
          }else if("exit".equals(method)){
              exit(request,response);
          }
      }
    
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          doGet(request, response);
      }
    
      public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
          System.out.println("处理登陆");
      }
    
      public void reg(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
          System.out.println("处理注册");
      }
    
      public void exit(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
          System.out.println("处理退出");
      }
    
    }
    
    

    运行效果:


    图片.png

    到这里我们的需求基本实现了,但是此处的servlet代码还有优化的空间,比如当用户的功能太多了,我们判断方法的逻辑也会变得很多,会出现很多if,else if的情况.所以这里我们将使用反射的来优化过多的逻辑判断问题.UserServlet进行如下优化:

    package com.xfz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.lang.reflect.Method;
    
    @WebServlet(urlPatterns = "/user")
    public class UserServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*
             * 获取提交的参数
             * 并判断内容调用方法
             * */
            String method = request.getParameter("method");
            //非空判断
            if(method == null || "".equals(method)){return;}
            //反射获取该类class对象
            Class clazz = this.getClass();
            //method就是方法名,反射获取方法
            try {
                Method md = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);
                md.invoke(this,request,response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
        public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理登陆");
        }
    
        public void reg(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理注册");
        }
    
        public void exit(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理退出");
        }
    
    }
    

    效果如下,相关处理依然能够实现,并且无需过多的逻辑判断:

    图片.png

    做到这里,我们发现在同一个业务下基本没有问题了,但是多个业务下就会出现代码重复的问题.
    这里的用户模块,订单模块,商品模块都会使用同一的步骤:获取客户端参数/反射技术获取方法/调用方法,因为他们是不同的业务模块,所以不能使用一个Servlet,那么对于这种情况下的相同代码我们可以使用继承的方式,进行向上抽取来优化过多重复代码的问题.如下:


    图片.png

    优化如下:

    第一步:创建BaseServlet类继承HttpServlet 重写doGet() doPost()方法
    第二步:将重复代码向上提取到该类doGet()方法中
    第三步:因为该类不需要被访问也不需要创建对象,所以无需注解,类也使用abstract修饰

        package com.xfz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.lang.reflect.Method;
    
    abstract class BaseServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*
             * 获取提交的参数
             * 并判断内容调用方法
             * */
            String method = request.getParameter("method");
            //非空判断
            if(method == null || "".equals(method)){return;}
            //反射获取该类class对象
            Class clazz = this.getClass();
            //method就是方法名,反射获取方法
            try {
                Method md = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);
                md.invoke(this,request,response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    

    UserServlet代码:
    第一步:继承BaseServlet类
    第二步:由于父类中有doGet()和doPost()方法,所以该类不需要,删除

    package com.xfz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(urlPatterns = "/user")
    public class UserServlet extends BaseServlet {
    
        public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理登陆");
        }
    
        public void reg(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理注册");
        }
    
        public void exit(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("处理退出");
        }
    
    }
    
    

    效果如图:


    图片.png
    图片.png

    到这里对于多个Servlet的抽取优化基本完成,当有别的业务如Order订单逻辑需要我们处理时,也只需新建普通类添加注解并继承BaseServlet,写入相关功能方法即可.

    示例:
    客户端JSP代码:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <a href="${pageContext.request.contextPath}/order?method=add">添加订单</a><br>
    <a href="${pageContext.request.contextPath}/order?method=remove">移除订单</a><br>
    <a href="${pageContext.request.contextPath}/order?method=show">查看订单</a>
    </body>
    </html>
    
    

    OrderServlet代码:

        package com.xfz.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    
    @WebServlet(urlPatterns = "/order")
    public class OrderServlet extends BaseServlet{
        public void add(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
            System.out.println("添加订单");
        }
    
        public void remove(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("移除订单");
        }
    
        public void show(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
            System.out.println("查看订单");
        }
    }
    
    

    效果如下依然可以实现,并且更加简洁:


    图片.png

    相关文章

      网友评论

        本文标题:Servlet抽取技术简单案例

        本文链接:https://www.haomeiwen.com/subject/dvfecqtx.html