JavaWeb:(十)MVC

10.1 MVC概念

在最开始的Web结构中,一个请求需要用一个Servlet来进行处理,这样做的坏处是,一个项目往往有成百上千个请求,那就需要成百上千的Servlet,文件多,代码冗余,这是令人无法接受的。所以我们引入MVC的架构模式。

MVC概念

M:Model模型

V:View视图

C:Controller控制器

MVC是在表述层开发中运用的一种设计理念。主张把封装数据的『模型』显示用户界面的『视图』、**协调调度的『控制器』**分开。

在MVC中,控制器是核心,控制着用户请求到业务逻辑的映射关系。通过MVC架构,后端的业务逻辑可以从冗余的代码中解放出来,从而专注于业务的处理,将请求映射、参数获取、视图跳转这些统一的操作交给控制器来做,从而能一定程度上实现代码解耦。

10.2 MVC和三层架构之间关系

./images

10.3 控制器实例代码(DispatcherServlet)

控制器代码总结:

  1. 通过请求路径获取处理本次请求的controller对象
  2. 通过请求中的operate参数,获取controller对象中对本次请求的具体处理方法
  3. 通过反射获取方法的真实参数名,通过参数名从请求域中获取参数
  4. 通过方法的返回值进行视图跳转
package servlet;

import impl.FruitDAOImpl;
import org.junit.Test;
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 pojo.Fruit;
import util.JDBCUtils;
import util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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 java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.Connection;
import java.util.HashMap;

@WebServlet(urlPatterns = "*.do")
public class DispatcherServlet extends ViewBaseServlet {

    private HashMap<String, Object> beanMap = new HashMap<>();

    /**
     * 构造方法:解析配置文件,将配置文件中的每个bean标签都加载一个实例对象,并保存到beanMap中
     * 在这里主要是获取统一的执行对象
     * 比如关于fruit的一系列操作都封装在fruitController中,于是beanMap中初始化一个fruitController对象用于执行相关方法
     */
    public DispatcherServlet(){
        try {
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("application-context.xml");
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(inputStream);

            NodeList beanNodeList = document.getElementsByTagName("bean");
            for (int i = 0; i < beanNodeList.getLength(); i++) {
                Node beanNode = beanNodeList.item(i);
                if (beanNode.getNodeType() == Node.ELEMENT_NODE){
                    Element beanElement = (Element) beanNode;
                    String beanId = beanElement.getAttribute("id");
                    String aClass = beanElement.getAttribute("class");
                    Object beanObj = Class.forName(aClass).getDeclaredConstructor().newInstance();
                    beanMap.put(beanId, beanObj);
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        //解析请求路径
        String servletPath = request.getServletPath();
        servletPath = servletPath.substring(1);
        servletPath = servletPath.substring(0, servletPath.lastIndexOf(".do"));

        // 通过请求路径获取要执行的方法的controller类对象
        Object controllerBeanObj = beanMap.get(servletPath);

        //通过请求的operate参数,获取处理本次请求的方法
        String operate = request.getParameter("operate");
        if(StringUtils.isEmpty(operate)){
            operate = "index";
        }

        try {
            // 获取controller类对象中要执行的方法
            Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();
            for (Method method : methods) {
                if (operate.equals(method.getName())){
                    //获取方法的参数
                    Parameter[] parameters = method.getParameters();
                    Object[] parametersValues = new Object[parameters.length];
                    for (int i = 0; i < parameters.length; i++) {
                        //获取方法的参数名,根据参数名进行传参
                        //Java8新特性可以直接获取方法的参数的真实名称,需要在Java Compiler中设置参数 -parameters
                        //如果是maven项目,想要获取方法参数真实名称则需要单独在pom.xml文件中进行配置,配置参数在文末列出
                        if ("request".equals(parameters[i].getName())){
                            parametersValues[i] = request;
                        } else if ("response".equals(parameters[i].getName())){
                            parametersValues[i] = response;
                        } else if ("session".equals(parameters[i].getName())){
                            parametersValues[i] = request.getSession();
                        } else {
                            String parameterName = parameters[i].getName();
                            String parameterValue = request.getParameter(parameterName);
                            String typeName = parameters[i].getType().getName();
                            if (parameterValue != null){
                                if ("java.lang.Integer".equals(typeName)){
                                    parametersValues[i] = Integer.parseInt(parameterValue);
                                } else {
                                    parametersValues[i] = parameterValue;
                                }
                            }
                        }
                    }

                    method.setAccessible(true);
                    String methodReturn = (String) method.invoke(controllerBeanObj, parametersValues);
                    if (methodReturn.startsWith("redirect:")){
                        String redirect = methodReturn.substring("redirect:".length());
                        response.sendRedirect(redirect);
                    } else{
                        processTemplate(methodReturn, request, response);
                    }
                }
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值