BaseServlet工具类

写一个项目往往需要N多个Servlet,而且一个servlet只有一个doGet或doPoset.如果项目比较大,Servlet的数量会比较惊人。为了避免Servlet数量过多,我们可以在一个Servlet中写多个接收请求的方法。

具体思路:Servlet中处理请求的方法是service()方法,这说明我们需要让service()方法去调用其他方法。例如调用add()、mod()、del()、all()等方法。可以在请求时,添加一个参数,表示需要调用的方法名,然后在Servlet中判断。

实例代码:AServlet.java

public class AServlet extends javax.servlet.http.HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //获取method参数值
        String methodName=request.getParameter("method");
        
        //method参数值不能为空或null
        if(methodName==null||methodName.trim().equals("")){
            throw new RuntimeException("请输入需要访问的方法名");
        }

        //判断调用
        if(methodName.equals("addUser")){
            addUser(request,response);
        }else if(methodName.equals("updateUser")){
            updateUser(request,response);
        }else if(methodName.equals("queryUser")){
            queryUser(request,response);
        }else if(methodName.equals("deleteUser")){
            deleteUser(request,response);
        }
    }

    protected void addUser(HttpServletRequest request, HttpServletResponse response)
            throws javax.servlet.ServletException, IOException {
        System.out.println("addUser");
    }

    protected void updateUser(HttpServletRequest request, HttpServletResponse response)
            throws javax.servlet.ServletException, IOException {
        System.out.println("updateUser");
    }

    protected void queryUser(HttpServletRequest request, HttpServletResponse response)
            throws javax.servlet.ServletException, IOException {
        System.out.println("queryUser");
    }

    protected void deleteUser(HttpServletRequest request, HttpServletResponse response)
            throws javax.servlet.ServletException, IOException {
        System.out.println("deleteUser");
    }
}

这里需要注意:因为Servlet使通过service来调用其他方法,请求处理方法的签名必须与service相同:即返回值和参数,以及声明的异常都相同!

上面通过判断来决定调用那个方法,不方便扩展。这里我们通过反射,来自动调用对应的方法。

代码实现AServlet.java

public class AServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //获取method参数值
        String methodName=request.getParameter("method");

        //method参数值不能为空或null
        if(methodName==null||methodName.trim().equals("")){
            throw new RuntimeException("请输入需要访问的方法名");
        }

        //获得当前的类对象
        Class clazz=this.getClass();

        //创建反射中的方法对象
        Method method=null;

        try {
            /**
             * 调用类的getMethod获得方法
             * 第一个参数:类名
             * 后面的参数:方法的参数类型
             */
            method= clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(methodName+"(HttpServletRequest,HttpServletResponse)方法不存在!");
        }

        try {
            /**
             * 对比正常调用方法:this.addUser(request,response)
             */
            method.invoke(this,request,response);
        } catch (Exception e) {
            System.out.println(methodName+"(HttpServletRequest,HttpServletResponse)方法内部出现了异常!");
            throw new RuntimeException(e);
        }
    }

    protected void addUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("addUser");
    }

    protected void updateUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("updateUser");
    }

    protected void queryUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("queryUser");
    }

    protected void deleteUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("deleteUser");
    }
}

这里的Method getDeclaredMethod()和Method getMethod()需要区分一下:

  • getMethod():访问本类中定义的公共方法
  • getDeclaredMethod():访问本类中定义的所有方法

再进一步考虑,如果有多个Servlet,反射代码可以只写一次吗?

解决方案就是,将反射写在一个所有Servlet都继承的父类里面,下面我们就写一个这样的父类:BaseServlet.java

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //获取method参数值
        String methodName=request.getParameter("method");

        //method参数值不能为空或null
        if(methodName==null||methodName.trim().equals("")){
            throw new RuntimeException("请输入需要访问的方法名");
        }

        //获得当前的类对象
        Class clazz=this.getClass();

        //创建反射中的方法对象
        Method method=null;

        try {
            /**
             * 调用类的getMethod获得方法
             * 第一个参数:类名
             * 后面的参数:方法的参数类型
             */
            method= clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(methodName+"(HttpServletRequest,HttpServletResponse)方法不存在!");
        }

        try {
            /**
             * 对比正常调用方法:this.addUser(request,response)
             */
            method.invoke(this,request,response);
        } catch (Exception e) {
            System.out.println(methodName+"(HttpServletRequest,HttpServletResponse)方法内部出现了异常!");
            throw new RuntimeException(e);
        }
    }
}

AServlet.java

public class AServlet extends BaseServlet {

    protected void addUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("addUser");
    }

    protected void updateUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("updateUser");
    }

    protected void queryUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("queryUser");
    }

    protected void deleteUser(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("deleteUser");
    }
}

BServlet.java

public class BServlet extends BaseServlet {
    protected void addNews(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        System.out.println("addNews");
    }

    protected void editNews(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("editNews");

    }
}

这里补充一个包含转发重定向的处理技巧:

很多时候我们访问函数需要实现转发重定项等作用,如果每次都在函数中写,可能有很多重复的代码。现在我们有了BaseServlet,可以把转发重定项等代码在BaseServlet中写,这样只要写一遍。

重写BServlet

public class BServlet extends BaseServlet {
    protected String addNews(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("addNews");
        //返回转发
        return "f:/index.jsp";

    }

    protected String editNews(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("editNews");
        //返回重定项
        return "r:"+request.getContextPath()+"/index.jsp";

    }
}

在需要转发重定项的函数直接在函数结束时返回一个字符串,包含一个标志字母(如f或r等),以及地址。

重写BaseServlet

public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //获取method参数值
        String methodName=request.getParameter("method");

        //method参数值不能为空或null
        if(methodName==null||methodName.trim().equals("")){
            throw new RuntimeException("请输入需要访问的方法名");
        }

        //获得当前的类对象
        Class clazz=this.getClass();

        //创建反射中的方法对象
        Method method=null;

        try {
            /**
             * 调用类的getMethod获得方法
             * 第一个参数:类名
             * 后面的参数:方法的参数类型
             */
            method= clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(methodName+"(HttpServletRequest,HttpServletResponse)方法不存在!");
        }

        try {
            /**
             * 对比正常调用方法:this.addUser(request,response)
             *
             * 返回值为一个字符串
             * 包好:表示为转发或是重定项
             * r:代表重定项
             * f:代表转发
             */
            String retstr = (String) method.invoke(this,request,response);

            //返回的字符串不能为空或是null
           if(retstr==null||retstr.equals("")){
               return;
           }

            if (retstr.contains(":")) {
                int index=retstr.indexOf(":");
                if(retstr.charAt(0)=='f'){//转发
                    request.getRequestDispatcher(retstr.substring(index+1)).forward(request,response);
                }else if(retstr.charAt(0)=='r'){//重定向
                    response.sendRedirect(retstr.substring(index+1));
                }
            }

        } catch (Exception e) {
            System.out.println(methodName+"(HttpServletRequest,HttpServletResponse)方法内部出现了异常!");
            throw new RuntimeException(e);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/SICAUliuy/article/details/88851203