Java Web ——MVC基础框架讲解及代码演示(上)

简介: Java Web ——MVC基础框架讲解及代码演示

了解一下类似Spring MVC框架的底层实现

相信看完这个短文,MVC你就懂了,还不懂请艾特我······

带着问题去学习

  • MVC到底是什么?
  • 如何实现MVC?

开始!

MVC是什么?

Web开发

在讲MVC之前,还是简要介绍一下Web开发吧,相信搞程序的或多或少都知道Web编程、Socket编程等等。

其实开发Web应用最原始的方式面向Http连接的底层进行开发,自己编写Web服务,需要了解和考虑的内容包括但不限于:Socket编程、端口号、报文处理、IO多路复用、线程池等等。

举个例子,用Java来编写一个Http服务器:

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8080); // 监听指定端口
        System.out.println("server is running...");
        for (;;) {
            Socket sock = ss.accept();
            System.out.println("connected from " + sock.getRemoteSocketAddress());
            Thread t = new Handler(sock);
            t.start();
        }
    }
}

class Handler extends Thread {
    Socket sock;

    public Handler(Socket sock) {
        this.sock = sock;
    }

    public void run() {
        try (InputStream input = this.sock.getInputStream()) {
            try (OutputStream output = this.sock.getOutputStream()) {
                handle(input, output);
            }
        } catch (Exception e) {
            try {
                this.sock.close();
            } catch (IOException ioe) {
            }
            System.out.println("client disconnected.");
        }
    }

    private void handle(InputStream input, OutputStream output) throws IOException {
        System.out.println("Process new http request...");
        var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
        var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
        // 读取HTTP请求:
        boolean requestOk = false;
        String first = reader.readLine();
        if (first.startsWith("GET / HTTP/1.")) {
            requestOk = true;
        }
        for (;;) {
            String header = reader.readLine();
            if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
                break;
            }
            System.out.println(header);
        }
        System.out.println(requestOk ? "Response OK" : "Response Error");
        if (!requestOk) {
            // 发送错误响应:
            writer.write("HTTP/1.0 404 Not Found\r\n");
            writer.write("Content-Length: 0\r\n");
            writer.write("\r\n");
            writer.flush();
        } else {
            // 发送成功响应:
            String data = "<html><body><h1>Hello, world!</h1></body></html>";
            int length = data.getBytes(StandardCharsets.UTF_8).length;
            writer.write("HTTP/1.0 200 OK\r\n");
            writer.write("Connection: close\r\n");
            writer.write("Content-Type: text/html\r\n");
            writer.write("Content-Length: " + length + "\r\n");
            writer.write("\r\n"); // 空行标识Header和Body的分隔
            writer.write(data);
            writer.flush();
        }
    }
}

一个Http服务器,本质上来说就是TCP服务器,处理流程就是服务器一直监听端口,客户端向指定端口发送请求,服务器接收请求进行相应的逻辑处理,而后将处理结果又返回给客户端,最后在客户端浏览器上进行展示。更详细的玩意儿还是参见《Unix网络编程》那本书的例子,可以模仿C语言写个Java的客户端

但是在实际开发过程中,这些基础、底层的工作,就是重复造轮子,需要耗费大量的时间!

为了方便开发,将这些底层工作封装到一个库中——Servlet中,于是后来的程序员只需要基于Servlet的API来开发Web应用即可,不用再去管这些端口啊、IO多路复用什么的。

基于Servlet开发

基于Servlet开发可以大大减小开发Web服务的复杂程度,例如只需要几行代码,就可以让服务端相应客户端对主页的请求:

//原址https://www.liaoxuefeng.com/wiki/1252599548343744/1304265949708322
//WebServlet注解表示这是一个Servlet,并将url地址为"/"的请求映射到这个类中进行处理
@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, 
                         HttpServletResponse resp)
        throws ServletException, IOException {
        // 设置响应类型:
        resp.setContentType("text/html");
        // 获取输出流:
        PrintWriter pw = resp.getWriter();
        // 写入响应:
        pw.write("<h1>Hello, world!</h1>");
        // flush强制输出:
        pw.flush();
    }
}

一个Web应用其实就是由一个或多个Servlet组成的,每个Servlet通过注解说明自己负责的路径Url,并通过实现doGet和doPost方法来进行相应的逻辑处理。比如处理GET方法,就覆写doGet()方法:

@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ...
        }
}

其他的如POST等请求方法也是类似的。

可以看到,当有了Servlet之后,开发Web应用就变得简洁了起来,只需要编写处理对应url的逻辑处理即可。

但是,你们有没有发现一个问题——在Java代码里出现了跟前端有关的代码。在Servlet程序中,输出HTML的方式如下:

PrintWriter pw = resp.getWriter();
pw.write("<html>");
pw.write("<body>");
pw.write("<h1>Welcome, " + name + "!</h1>");
pw.write("</body>");
pw.write("</html>");
pw.flush();

上述这种输出HTML的步骤较为繁琐,而且容易出错,并且也不像直接编写HTML网页那么直观(比如JS、CSS语言),虽然全栈工程师前后端都可以care,不过在项目开发中还是前端和后端的东西各自分开最好,才能使两者的开发效率最高。


为了解决这个问题,后面出现了JSP(Java Server Pages)语言。


JSP代码类似于html语言,并且其中还可以嵌入Java代码,进行变量插入、变量输出等操作:

//原址:https://www.liaoxuefeng.com/wiki/1252599548343744/1266262958498784
<html>
<head>
<title>Hello World - JSP</title>
</head>
<body>
<%-- JSP Comment --%>
<h1>Hello World!</h1>
<p>
<%
out.println("Your IP address is ");
%>
    <span style="color:red">
    <%= request.getRemoteAddr() %>
    </span>
    </p>
    </body>
</html>

不过这种方式(JSP)虽然可以很方便的输出HTML,并在其中实现一定的动态内容,运行简单的代码,但是写起Java来也忒不适应了吧,总感觉怪怪的。


另外,Servlet简化了Web应用的开发,可以基于Java语言实现复杂的业务逻辑,但是不太适合输出HTML。


那么,有没有一种方式可以结合两者,从而是两者相辅相成呢?


有的!那就是MVC!

MVC设计模式

先给出MVC设计模式的简单定义——Model-View-Controller:

  • Model(模型)是前后端定义的数据传输单元,通常前端只是需要后端提供一些数据来展示而已,比如用户名、处理结果来,需要HTML输出的东西;
  • View(视图)的工作就是接收后端发过来的Model,取出数据,然后写入Html中;
  • Controller(控制器)其实就是业务逻辑,类似于之前的Servlet开发,区别在于现在将处理结果都放在Model里,然后发给View;

来个例子吧,实现用户登录,获取信息

首先,我们编写了两个JavaBean(JavaBean简单来说就是一个可以放入数据和取出数据的类),也就是之前说的Model

//源码:https://www.liaoxuefeng.com/wiki/1252599548343744/1266264917931808
public class User {
    public long id;
    public String name;
    public School school;
}
public class School {
    public String name;
    public String address;
}

接着,来实现Controller,在UserServlet中实现从数据库读取User、School等信息,并放入Request中,再发送给user.jsp,也就是View进行渲染处理:

@WebServlet(urlPatterns = "/user")
public class UserServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 假装从数据库读取:
        School school = new School("No.1 Middle School", "101 South Street");
        User user = new User(123, "Bob", school);
        // 放入Request中:
        req.setAttribute("user", user);
        // forward给user.jsp:
        req.getRequestDispatcher("/WEB-INF/user.jsp").forward(req, resp);
    }
}

View——user.jsp负责将接收到的user信息进行渲染展示,即写入Html中:

<%@ page import="com.itranswarp.learnjava.bean.*"%>
<%
User user = (User) request.getAttribute("user");
%>
    <html>
    <head>
    <title>Hello World - JSP</title>
    </head>
    <body>
    <h1>Hello <%= user.name %>!</h1>
    <p>School Name:
<span style="color:red">
<%= user.school.name %>
    </span>
    </p>
    <p>School Address:
<span style="color:red">
<%= user.school.address %>
    </span>
    </p>
    </body>
</html>

以上,就完成了一个简单的web应用,在浏览器访问http://localhost:8080/user,结果如下:

捋一捋,用一个结构图来描述上述代码:

简单来说,就是将整个Web开发分成了三个部分:逻辑处理、前端展示、数据传输,分别代表Controller、View、Model。

这种方式有什么好处?分工明确、开发简单。

Controller就好好关注逻辑处理,比如访问数据库啦、进行复杂的逻辑交互等等;View就关注如何让界面好看就完了,比如用模板引擎写出好看的界面,留几个空白给Model进行展示就ok了!


有关模板引擎的具体内容,可以了解:https://blog.csdn.net/qq_42266891/article/details/108265478


实现一个简单MVC框架

Java Web ——MVC基础框架讲解及代码演示(下):https://developer.aliyun.com/article/1508612

相关文章
|
3天前
|
SQL 安全 PHP
PHP 自发布以来一直在 Web 开发领域占据重要地位,PHP 8 更是带来了属性、刚性类型等新特性。
【10月更文挑战第1天】PHP 自问世以来,凭借其易用性和灵活性,在 Web 开发领域迅速崛起。从简单的网页脚本语言逐步演进为支持面向对象编程的现代语言,尤其自 PHP 5.3 引入命名空间后,代码组织和维护变得更加高效。PHP 7 的性能优化和 PHP 8 的新特性(如属性和刚性类型)进一步巩固了其地位。框架如 Laravel、Symfony、Yii2 和 CodeIgniter 等简化了开发流程,提高了效率和安全性。
22 2
|
1天前
|
设计模式 JavaScript 前端开发
浅谈JavaScript 框架在现代 Web 开发中的作用
浅谈JavaScript 框架在现代 Web 开发中的作用
23 12
|
1天前
|
人工智能 缓存 Java
深入解析Spring AI框架:在Java应用中实现智能化交互的关键
【10月更文挑战第12天】Spring AI 是 Spring 框架家族的新成员,旨在满足 Java 应用程序对人工智能集成的需求。它支持自然语言处理、图像识别等多种 AI 技术,并提供与云服务(如 OpenAI、Azure Cognitive Services)及本地模型的无缝集成。通过简单的配置和编码,开发者可轻松实现 AI 功能,同时应对模型切换、数据安全及性能优化等挑战。
|
1天前
|
存储 SQL 数据库
使用Python和Flask框架创建Web应用
【10月更文挑战第3天】使用Python和Flask框架创建Web应用
12 1
|
2天前
|
前端开发 Java API
JAVA Web 服务及底层框架原理
【10月更文挑战第1天】Java Web 服务是基于 Java 编程语言用于开发分布式网络应用程序的一种技术。它通常运行在 Web 服务器上,并通过 HTTP 协议与客户端进行通信。
9 1
|
2天前
|
开发框架 前端开发 数据库
使用Django框架构建一个完整的Web应用
【10月更文挑战第2天】使用Django框架构建一个完整的Web应用
12 1
|
2月前
|
存储 JavaScript NoSQL
构建高效Web应用:使用Node.js和Express框架
【8月更文挑战第30天】本文将引导你了解如何使用Node.js和Express框架快速搭建一个高效的Web应用。通过实际的代码示例,我们将展示如何创建一个简单的API服务,并讨论如何利用中间件来增强应用功能。无论你是新手还是有经验的开发者,这篇文章都将为你提供有价值的见解。
|
15天前
|
Web App开发 JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的深度整合
【9月更文挑战第28天】在现代Web开发领域,Node.js和Express框架的结合已成为打造高性能、易扩展应用的黄金组合。本文将深入探讨如何利用这一技术栈优化Web应用架构,提供具体实践指导,并分析其性能提升的内在机制。通过代码示例,我们将展示从基础搭建到高级功能的实现过程,旨在为开发者提供一条清晰的学习路径,以实现技术升级和项目效率的双重提升。
35 3
|
15天前
|
JSON JavaScript 前端开发
构建高效Web应用:Node.js与Express框架的完美结合
【9月更文挑战第28天】在现代Web开发中,Node.js和Express框架的结合为创建高性能、易扩展的应用提供了强有力的支持。本文将深入探讨如何利用这两种技术构建一个简单但功能强大的Web服务,同时提供代码示例以加深理解。
|
2月前
|
JavaScript PHP 开发者
PHP中的异常处理与自定义错误处理器构建高效Web应用:Node.js与Express框架实战指南
【8月更文挑战第27天】在PHP编程世界中,异常处理和错误管理是代码健壮性的关键。本文将深入探讨PHP的异常处理机制,并指导你如何创建自定义错误处理器,以便优雅地管理运行时错误。我们将一起学习如何使用try-catch块捕获异常,以及如何通过set_error_handler函数定制错误响应。准备好让你的代码变得更加可靠,同时提供更友好的错误信息给最终用户。