3.3 下一步,我们改动传参

3.3.1 EmpController 代码

 

package com.hy.controller;

public class EmpController {

   public String index() {

      System.out.println("EmpController...index");

      return "forward:/WEB-INF/emp/index.jsp";

   }

  

   public String login(String ename,String pwd) {

      return "redirect:emp.do?ac=index";

   }

}

3.3.2 变成参数后,谁给我们传参?

将获取参数的过程 — request.getParameter(“xxx”),统一抽取到中央调度器DispatcherServlet中,来统一获取请求参数。

 

如果在EmpController中写个delete方法参数名叫什么?如果写一个insert,update方法呢,每个方法的参数都不一样。所以我到底要获取哪些参数是,根据当前这个方法的方法签名来决定的

 

 

3.3.3 在DispatcherServlet添加统一获取请求参数的代码。

 

 

访问测试:http://127.0.0.1:8080/mymvc3/emp.do?ac=login

 

报错:

 

因为EmpController的方法中没有,HttpServletRequest和HttpServletResponse了。那么这句代码就无法获取到了。

Method method = xxxController.getClass().getDeclaredMethod(ac, HttpServletRequest.class,

                HttpServletResponse.class);

 

3.3.4 修改DispatcherServlet代码

修改代码,通过反射机制获取所有的方法。然后只根据方法名来做判断。

package com.hy.servlet;

 

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Parameter;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

 

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 javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

 

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

 

import com.hy.utils.StringUtil;

 

@WebServlet("*.do")

public class DispatcherServlet extends HttpServlet {

    private Map<String, Object> map = new ConcurrentHashMap<>();

 

    public DispatcherServlet() {

        try {

            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("applicationContext.xml");

            // 1,通过工厂模式,创建documentBuilderFactory工厂对象

            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

 

            // 2,创建DocumentBuilder对象

            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

 

            // 3,得到Document对象( 注意导入org.w3c.dom包中的)

            Document document = documentBuilder.parse(inputStream);

 

            // 4,获得所有的bean标签

            NodeList nodeList = document.getElementsByTagName("bean");

            for (int i = 0; i < nodeList.getLength(); i++) {

               Node node = nodeList.item(i);

 

               if (node.getNodeType() == Node.ELEMENT_NODE) {

                   // (注意导入org.w3c.dom包中的)

                   // 强转成Element类的对象,里面有比Node类更方便的方法

                   Element element = (Element) node;

 

                   String id = element.getAttribute("id");

                   String className = element.getAttribute("class");

                   boolean flag = map.containsKey(id);

                   if (flag == true)

                       return;

                   Object o = Class.forName(className).newInstance();

                   map.put(id, o);

               }

            }

        } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException

               | InstantiationException | IllegalAccessException e) {

            e.printStackTrace();

        }

    }

 

    @Override

    protected void service(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        // 设置编码

        request.setCharacterEncoding("UTF-8");

        response.setCharacterEncoding("UTF-8");

        response.setContentType("text/html;charset=UTF-8");

 

        // 假设url是: http://localhost:8080/mymvc2/hello.do

        // ServletPath是Servlet的访问路径: /hello.do

        // 思路是:

        // 第1步: /hello.do -> hello 或者 /book.do -> book

        // 第2步: hello -> HelloController 或者 book -> BookController

        String servletPath = request.getServletPath(); // /hello.do

        int lastDotIndex = servletPath.lastIndexOf(".do");

        servletPath = servletPath.substring(1, lastDotIndex); // hello

 

        // 通过ServletPath获取对应的Controller对象

        Object xxxController = map.get(servletPath);

 

        String ac = request.getParameter("ac");

        System.out.println("=======ac ===" + ac + "======");

        if (StringUtil.isEmpty(ac))

            ac = "index";

 

        String methodReturnStr = null;

        try {

            // 这里只能try...catch异常,因为在重写的方法里,不能抛出比父类更大的异常

 

            Method[] methods = xxxController.getClass().getDeclaredMethods();

 

            if (methods != null) {

               for (Method method : methods) {

                   if (ac.equals(method.getName())) {

                       // 1,统一获取请求参数

                       // 1.1 获取当前方法的参数,返回参数数组

                       Parameter[] parameters = method.getParameters();

                       System.out.println("===========Dispatcher=========" + parameters);

 

                       // 2. xxxController中的方法调用

                       Object returnObj = method.invoke(xxxController, request, response);

 

                       // 3, 视图跳转处理

                       if (returnObj != null) {

                           methodReturnStr = (String) returnObj;

                           if (methodReturnStr.startsWith("redirect:")) {

                               String redirectStr = methodReturnStr.substring("redirect:".length());

                               response.sendRedirect(request.getContextPath() + "/" + redirectStr);

                               return;

                           } else if (methodReturnStr.startsWith("forward:")) {

                               String forwardtStr = methodReturnStr.substring("forward:".length());

                               request.getRequestDispatcher(forwardtStr).forward(request, response);

                               return;

                           }

                       }

                       return;

                   }

               }

              

               throw new RuntimeException("ac值违法");

            }

        } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {

            e.printStackTrace();

        }

    }

}

 

3.3.5 测试:模拟登录

http://127.0.0.1:8080/mymvc/emp.do?ac=login

posted @ 2022-06-07 13:14  费凡  阅读(19)  评论(0编辑  收藏  举报