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中的某方法执行完之后,会返回一个字符串,根据所得的字符串进行截取、判断,然后完成相应的转发或者重定向。

 

原文地址:https://www.cnblogs.com/xjs1874704478/p/10940405.html