Servlet抽取技术简单案例

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

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

Servlet抽取技术简单案例_第1张图片
image

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

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

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

Servlet抽取技术简单案例_第2张图片
image

环境搭建:

Servlet抽取技术简单案例_第3张图片
图片.png

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

客户端JSP代码:



<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title

<%--
    向服务器发送请求
    约定好键值对数据,告知服务器
    请求的功能是什么
--%>

     登陆
注册
退出

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("处理退出");
  }

}

运行效果:


Servlet抽取技术简单案例_第4张图片
图片.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("处理退出");
    }

}

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

Servlet抽取技术简单案例_第5张图片
图片.png

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


Servlet抽取技术简单案例_第6张图片
图片.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("处理退出");
    }

}

效果如图:


Servlet抽取技术简单案例_第7张图片
图片.png

Servlet抽取技术简单案例_第8张图片
图片.png

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

示例:
客户端JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


添加订单
移除订单
查看订单

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("查看订单");
    }
}

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


Servlet抽取技术简单案例_第9张图片
图片.png

你可能感兴趣的:(Servlet抽取技术简单案例)