学习JavaWeb时候学习的一个DispatcherServlet.....

本文介绍了在学习JavaWeb时,如何通过自定义DispatcherServlet来实现动态请求映射。详细步骤包括:获取请求URI,检查类中是否存在对应方法,处理方法参数,通过反射执行方法,以及判断并处理方法返回值进行页面跳转。

1.写一个类继承serlve

1.1类中先获取请求的URI(请求地址)

就是找到那个请求中对应的方法.

/**
     * 根据uri获取截取action
     * @param requestURI
     * @return
     */
    private String getActionName(String requestURI) {
        //1.获取"/"的最后索引,最后一个斜杠就是action
        int index = requestURI.lastIndexOf("/");

        return requestURI.substring(index+1);
    }

1.2判断该类中有没有该方法

/**
     * 找类中有没有包含actionName的方法
     * @param actionName
     * @return
     */
    private Method findActionMethod(String actionName) {
        //1.首先获取类中所有的方法名称
        Method[] methods = this.getClass().getMethods();
        //2.遍历,判断是否包含actionName
        for (int i = 0; i < methods.length; i++) {
            //3.判断类名是否包含actionName
            if (methods[i].getName().equals(actionName)){
                return methods[i];
            }
        }
        return null;
    }

1.3判断是否找到了类中对应的方法

 //3.判断是否找到了actionName
        if (actionMethod == null){
            System.out.println("没有找到相对于的"+actionName);
            return;
        }

1.4获取处理方法的参数(传递过来的参数)

1.4.1先获取参数的长度,创建Object数组存放参数
1.4.2获取方法的形参,遍历参数数组
1.4.3遍历获取参数,获取形参的名字,利用Request根据形参的名字获取请求传递的参数
1.4.4把参数放入数组中,返回出去
1.4.5判断参数的类型(对象,还是参数)

对象

1.利用反射获取实例(newInstace)

2.Reques.getParameterMap():获取对象所有的参数,封装在Map集合里面,对象的属性就是Map的Key,不存在就为Null

3.讲Map中的Key赋值给数组里面(BeanUtils.populate(数组,参数集合)

4.返回

属性

1.判断参数的类型(getType())

2.强转.

3.放进数组里面返回

 /**
     * 获取方法中的参数.存放数组并返回
     * @param actionMethod
     * @param request
     * @return
     */
    private Object[] actionMethodParameter(Method actionMethod, HttpServletRequest request,HttpServletResponse response) {
         //创建一个数组,放入参数.actionMethod.getParameterCount()==:参数的长度
        Object[] object = new Object[actionMethod.getParameterCount()];
        //1.获取方法的所有形参
        Parameter[] parameters = actionMethod.getParameters();

        //2.遍历参数数组
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];

            //2.1获取每个形参的名字
            String name = parameter.getName();
            Object  value = null;

            //2.2根据形参的名字从request中获取值
             value = request.getParameter(name);

            //2.3把获取的参数,放入数组里面
            if (value == null || "".equals(value)){

                //如果是一个对象,那么获取的value就是null,也可能是request或者
                if (EmpCantons.TYPE_HTTPSERVLETREQUEST.equals(parameter.getType().getSimpleName())){
                    value = request;
                }else if (EmpCantons.TYPE_HTTPSERVLETRESPONSE.equals(parameter.getType().getSimpleName())){
                    value = response;
                }else {
                    try {
                        //利用反射获取参数的实例.此时参数是对象
                        Object o = parameter.getType().newInstance();

                        //获取请求中的所有参数,Map中的key就是对象的属性.前提是对象中必须要有此属性
                        Map<String, String[]> parameterMap = request.getParameterMap();

                        //讲map中的数据拷贝到对象o中,没有的就为null
                        BeanUtils.populate(o,parameterMap);

                        value = o;//然后讲对象传入数组里面
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }

            }else {
                //获取参数的类型,然后讲参数强转
                Class<?> type = parameter.getType();
                if (type.getSimpleName().equals("Integer")){
                    value = Integer.parseInt(value.toString());
                }else if (type.getSimpleName().equals("Double")){
                    value = Double.parseDouble(value.toString());
                }//还有许多...
            }
            object[i] = value;

        }
        return object;

    }

1.5执行方法invoke

invoke(对象,方法参数)

 //5.调用方法
        try {
            //获取方法的返回值,actionMethod是需要执行的方法,obj是哪个对象.argsArray是方法的参数,invoke方法的返回值
            Object invoke = actionMethod.invoke(this, argsArray);
            if (invoke!= null){
                requestClient(invoke.toString(),request,response);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

1.6判断该方法的返回值

1.6.1先分割字符串,获取跳转的方式跳转的路径
1.6.2判断跳转的方式,在根据跳转的方法跳转到执行的路径
 private void requestClient(String resp, HttpServletRequest request, HttpServletResponse response) {

        //1.按照冒号分割
        String[] split = resp.split(":");

        //2.获取跳转的方式
       String type =  split[0] ;

       //3.获取跳转的页面的路径
        String page = split[1];

                //4.判断跳转的方式
                if (EmpCantons.TYPE_FORWARD.equals(type)){
                    try {
                        //转发会参考当前路劲,需要加上"/",从web根目录开始
                        request.getRequestDispatcher("/"+page).forward(request,response);
                    } catch (ServletException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else if (EmpCantons.TYPE_REDIRECT.equals(type)){
                    try {//重定向加了/就是从端口号开始,所以需要加上当前路劲
                        response.sendRedirect(request.getContextPath()+"/"+page);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

总结:本次也是学习,还有许多不足的地方,请各位大佬多多指教…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值