利用请求分发思想和反射技术进行代码优化

package com.csn.web;

import com.csn.pojo.vo.PageBean;
import com.csn.pojo.vo.Pagination;
import com.csn.pojo.vo.Result;
import com.csn.service.StudentService;
import com.csn.util.BaseController;

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.InvocationTargetException;
import java.lang.reflect.Method;

@WebServlet(urlPatterns = "/student/*")
public class StudentServlet extends HttpServlet {
    private StudentService service = new StudentService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求和响应编码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        /*todo:请求分发 优化代码**/

        //1.获取方法名(请求地址中的具体需求eg:(student/selectByPage) )
        StringBuffer requestURL = request.getRequestURL();
        //切割地址 student/selectByPage
        int Index = requestURL.lastIndexOf("/");//拿到"/"的索引位 赋值给Index
        //用String的substring(a,b)方法截取字符串 (左包右不包)
        // substring(a,b)中的参数b,其值最大可以为 父字符串的长度,但并不包含索引值为b的那个字符。
        String method = requestURL.substring(Index + 1,requestURL.length());//切割:student/selectByPage => selectByPag 将selectByPag赋值给method方法

 /*       if(method.equals("selectByPage")) {
            //分页查询功能
            selectByPage(request,response);
        }else if(method.equals("addStu")) {
            //添加数据功能
            addStu(request,response);
        } else if(method.equals("updateStu")) {
            //修改数据功能
            updateStu(request,response);
        } else if(method.equals("deleteStu")) {
            //删除数据功能
            deleteStu(request,response);
        }*/

        /*todo:反射 优化代码*/
        //找到要反射的类
        try {
            Class aClass = this.getClass();//=StudentServlet.class
            //找到类中指定的方法, 方法名method
            Method m = aClass.getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
            //调用方法
            m.setAccessible(true);//暴力反射 忽略访问权限的限制,直接调用 目的invoke方法的实现 权限检查
            //invok参数说明: this指调用此方法的对象,request,response 指调用参数
            /*
            *第一个参数:调用底层方法的对象
            *其他参数  :用于方法调用的参数
            * */
            m.invoke(this, request, response);//invoke()/**知识盲区,有机会再研究反射底层**/
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    private void deleteStu(HttpServletRequest request, HttpServletResponse response) {
    }


    private void updateStu(HttpServletRequest request, HttpServletResponse response) {
    }


    private void addStu(HttpServletRequest request, HttpServletResponse response) {

    }

    private void selectByPage(HttpServletRequest request, HttpServletResponse response) {

            //获取请求参数
            try{
                //获取请求体中的json格式参数并映射到Pagination中
                Pagination pagination = BaseController.parseJSON2Object(request, Pagination.class);

                //调用业务层的查询方法
                PageBean page = service.selectByPage(pagination);
                //响应给客户端
                //将Result对象转成json,并用响应给前端
                BaseController.printResult(response,new Result(true,"查询成功!",page));
            } catch (RuntimeException e) {
                e.printStackTrace();
                try {
                    BaseController.printResult(response, new Result(false, "查询失败o(╥﹏╥)o!"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

    }
}

invok()官方API:

invoke

public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。

如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。

如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。

 

参数:
obj - 从中调用底层方法的对象
args - 用于方法调用的参数
返回:
使用参数 argsobj 上指派该对象所表示方法的结果
抛出:
IllegalAccessException - 如果此 Method 对象强制执行 Java 语言访问控制,并且底层方法是不可访问的。
IllegalArgumentException - 如果该方法是实例方法,且指定对象参数不是声明底层方法的类或接口(或其中的子类或实现程序)的实例;如果实参和形参的数量不相同;如果基本参数的解包转换失败;如果在解包后,无法通过方法调用转换将参数值转换为相应的形参类型。
InvocationTargetException - 如果底层方法抛出异常。
NullPointerException - 如果指定对象为 null,且该方法是一个实例方法。
ExceptionInInitializerError - 如果由此方法引起的初始化失败。

 

posted @ 2021-07-09 21:55  java从精通到入门  阅读(69)  评论(0编辑  收藏  举报