IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JAVAWEB实训(1) 编写MVC框架 -> 正文阅读

[Java知识库]JAVAWEB实训(1) 编写MVC框架

目录

1. 什么是MVC框架?

1.1 MVC编程模式

1.2 MVC处理流程?

?2. 编写一个简单的MVC框架

2.1 注解

2.2 处理器映射器HandlerMapping

2.3 中央控制器DispatcherServlet

2.4 梳理MVC流程

?3. 源码


1. 什么是MVC框架?

MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。

1.1 MVC编程模式

  • V??即View视图,是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操作的方式。
  • M??即model模型,是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
  • C??即controller控制器,是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

1.2 MVC处理流程?

è?é?????è?°

【流程图说明】

1.用户发送请求至 前端控制器DispatcherServlet。

2.前端控制器DispatcherServlet收到请求后调用处理器映射器HandlerMapping。

3.处理器映射器HandlerMapping根据请求的Url找到具体的处理器,生成处理器对象Handler及处理器拦截器HandlerIntercepter(如果有则生成)一并返回给前端控制器DispatcherServlet。

4.前端控制器DispatcherServlet通过处理器适配器HandlerAdapter调用处理器Controller。

5.执行处理器(Controller,也叫后端控制器)

6.处理器Controller执行完后返回ModelAnView。

7.处理器映射器HandlerAdapter将处理器Controller执行返回的结果ModelAndView返回给前端控制器DispatcherServlet。

8.前端控制器DispatcherServlet将ModelAnView传给视图解析器ViewResolver。

9.视图解析器ViewResolver解析后返回具体的视图View。

10.前端控制器DispatcherServlet对视图View进行渲染视图(即:将模型数据填充至视图中)

11.前端控制器DispatcherServlet响应用户。

【此处摘自CSDN博主「皓月星辰_w」的原创文章:MVC框架详解(资源整理)_皓月星辰-CSDN博客_mvc框架

?2. 编写一个简单的MVC框架

观察下面这个类中的方法, 这里指定了url和相应的处理器,那么如何才能让用户在浏览器输入url后,后台正确地调用对应的处理器呢?

2.1 注解

?首先每个方法(处理器)是通过注解与url关联的(value):

  • @Target(ElementType.METHOD)表示是方法注解
  • @Retention(RetentionPolicy.RUNTIME)表示注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;一般如果需要在运行时去动态获取注解信息,那只能用?RUNTIME 注解
  • @Documented表示这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。

ResponseBody:


import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
 * 被此注解添加的方法,会被用于处理请求
 * 方法返回的内容会被以文本的形式返回到客户端
 */
public @interface ResponseBody {
    String value();
}

?ResponseView:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
 * 被此注解添加的方法,会被用于处理请求
 * 方法返回的内容会直接重定向
 */
public @interface ResponseView {
    String value();
}

?2.2 处理器映射器HandlerMapping

处理器映射器类实际上是一个工具类:建立映射、存储映射、获取处理器

(1) 处理器映射器会在物理上建立url与处理器之间的映射:

private static Map<String,MVCMapping> data = new HashMap<>();

?用一个HashMap来保存String类型的url与“处理器对象”之间的映射关系,这个处理器对象我们用一个静态内部类进行封装:

/**
 * 映射对象,每一个对象封装一个方法,用于处理请求
 */
public static class MVCMapping{
    private Object object;
    private Method method;
    private ResponseType type;
}

这是因为我们处理请求的类是通过配置文件进行配置的:application.properties

一个类中间可能包含多个处理请求的方法method,注解的类型表示处理器返回的类型type

(2) 处理器映射器向外提供方法:通过url获取处理器

public static MVCMapping get(String uri)

(3) 处理器能够读取指定流中的处理器类,以方法为单位解析成处理器对象MVCMapping,并生成映射:

public static void load(InputStream is) throws IOException {
        Properties ppt = new Properties();
        ppt.load(is);
        //获取配置文件中描述的一个个类
        Collection values = ppt.values();
        for (Object cla : values) {
            String className = (String) cla;
            try {
                //加载类
                Class c = Class.forName(className);
                //创建对象
                Object object = c.getConstructor().newInstance();
                //获取类的所有方法
                Method[] methods = c.getMethods();
                for (Method m : methods) {
                    Annotation[] annotations = m.getAnnotations();
                    if(annotations!=null) {
                        for (Annotation a : annotations) {
                            if (a instanceof ResponseBody){
                                //说明此方法用于返回字符串给客户端
                                MVCMapping mapping = new MVCMapping(object,m,ResponseType.TEXT);
                                Object o = data.put(((ResponseBody) a).value(),mapping);
                                if(o!=null){//存在的重复的请求地址
                                    throw new RuntimeException("请求地址重复:"+((ResponseBody) a).value());
                                }
                            }else if(a instanceof ResponseView){
                                //说明此方法用于返回界面给客户端
                                MVCMapping mapping = new MVCMapping(object,m,ResponseType.VIEW);
                                Object o = data.put(((ResponseView) a).value(),mapping);
                                if(o!=null){//存在的重复的请求地址
                                    throw new RuntimeException("请求地址重复:"+((ResponseBody) a).value());
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

上面代码中出现的ResponseType是自定义的枚举类型:表示响应的类型

public enum ResponseType {
    TEXT,VIEW;
}

2.3 中央控制器DispatcherServlet

(1)中央处理器继承了HttpServlet,在web.xml中我们对其进行配置:

  • 配置初始化文件
  • 配置处理所有的url请求
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>pers.xls.mvc.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contentConfigLocation</param-name>
        <param-value>application.properties</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

(2)通过重写Servlet的init方法获取初始化文件:

在这里调用处理器映射类来读取初始化文件建立映射

 @Override
    public void init(ServletConfig config) throws ServletException {
        String path = config.getInitParameter("contentConfigLocation");
        InputStream is = DispatcherServlet.class.getClassLoader().getResourceAsStream(path);
        try {
            HandlerMapping.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

(3)通过重写Service方法,根据接收的请求,获取对应的处理器,进行方法的调用:

 @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取用户请求的uri
        String uri = req.getRequestURI();
        HandlerMapping.MVCMapping mapping = HandlerMapping.get(uri);
        if (mapping==null){
            resp.sendError(404,"自定义MVC:映射地址不存在:"+uri);
            return;
        }
        Object obj = mapping.getObject();
        Method method = mapping.getMethod();
        Object result = null;
        try {
            result = method.invoke(obj,req,resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        switch (mapping.getType()){
            case TEXT:
                resp.getWriter().println((String) result);
                break;
            case VIEW:
                resp.sendRedirect((String) result);
                break;
        }
    }

2.4 梳理MVC流程

现在我们来梳理一下这个简单的MVC的处理流程:

  • 通过浏览器我们输入特定的?url?比如:localhost:8080/login.do

  • 中央控制器?DispatcherServlet?处理请求,如果是第一次访问,会调用 init 方法,加载src文件夹下的application.properties配置文件,将文件输入流传递给处理器映射器类?HandlerMapping 进行加载

  • 处理器映射器类 HandlerMapping 加载文件输入流,读取配置文件中的处理器类,分析出类中的含有特定注解的方法,建立url到“处理器对象MVCMapping”的映射,存储在哈希表中

  • 中央控制器?DispatcherServlet?继续调用service方法,调用处理器映射器类 HandlerMapping?的 get 方法获取请求uri对应的“处理器对象”如果获取不到,说明不存在该访问地址到处理器的映射,访问的内容不存在。从获取到的“处理器对象”中提取出相关的处理类对象、方法、响应类型,利用Java的反射机制,调用该方法:

?????????获取响应值,最后根据响应类型的不同对前台进行响应:

?3. 源码

链接:https://pan.baidu.com/s/1kfZAc-Z6DmK0cp1pcEfX7Q?
提取码:g8zx

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-07 13:43:18  更:2021-10-07 13:45:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:32:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码