牛客网论坛项目学习记录 1 - 环境配置与 Spring Boot

牛客网论坛项目

本文已被阅读过

Posted by Yuyao on November 9, 2021

1 搭建开发环境

1.1 Maven

Maven 介绍

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。 Maven 能够帮助开发者完成以下工作:

  • 构建
  • 文档生成
  • 报告
  • 依赖
  • SCMs
  • 发布
  • 分发
  • 邮件列表 本项目中使用 Maven 帮助管理项目依赖。

Maven 下载与安装

先决条件

由于 Maven 是基于 Java 开发的,其运行需要 JDK 的支持。特别得,需要 JDK 版本 >= 1.7

关于 Java JDK 的下载安装与开发环境配置,请参加 Java 开发环境配置

同时,请按照教程将环境变量中的 JAVA_HOME 和 CLASSPATH 以及 Path 成功配置并验证。

Maven 下载

下载链接 中的 “Files” 下选择版本下载即可。其中,有两种文件可供选择:

  • Binary archive 包含 Maven 源代码
  • Source archive 仅包含 Maven 运行程序

两种文件格式可供选择:

  • tar.gz 适用于 Linux / Unix / Mac OS 等系统
  • zip 适用于 Windows 系统

Maven 安装

Maven 下载成功后将其解压到选择文件夹下即可,此处假设解压到的文件夹是 “D:\Maven”。

进入路径后,能够发现解压出来的文件夹,名为 “apache-maven-3.8.3”。进入该文件夹,其中 “bin” 文件夹是我们关注的重点,”bin” 文件夹中的 “mvn” 即 Maven 的运行程序,Maven 相关命令格式都是通过 “mvn xxx”。在 “bin” 文件夹内,打开命令行,输入 “mvn –version” 测试 Maven 是否安装成功,如果有相应输出,证明安装成功。

为了使用方便,我们需要将该路径添加到环境变量中的 Path 中去。即将 “D:\Maven\apache-maven-3.8.3\bin” 添加到 Path 中。

最后,在命令行中其他路径下输入 “mvn –version” 测试配置是否成功。

Maven 基本用法

Maven 项目构建

Maven 的基本项目构建可以通过以下指令。

mvn archetype:generate -DgroupId=com.nowcoder.mavendemo1 -DartifactId=mavendemo1 -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

  • -DgroupId 指示公司名字,类似于 Java 中的包名
  • -DartifactId 指示新创建的项目名字
  • -DarchetypeArtifactId 指示创建项目用到的模板,对于基本项目构建,使用默认的 maven-archetype-quickstart 模板即可。
  • -DarchetypeVersion 代表版本,1.4 是官方推荐版本,无需修改
  • -DinteractiveMode 询问是否启用交互模式。如果启用,则每次操作的时候都会询问“是”或“否”

可能的报错

如果执行上述指令后,有如下报错:

The goal you specified requires a project to execute but there is no POM in this directory (D:\MavenTest). Please verify you invoked Maven from the correct directory. -> [Help 1]

解决办法为每个命令参数加上双引号”“即可,即:

mvn archetype:generate "-DgroupId=com.nowcoder.mavendemo1" "-DartifactId=mavendemo1" "-DarchetypeArtifactId=maven-archetype-quickstart" "-DarchetypeVersion=1.4" "-DinteractiveMode=false"

构建结果

构建成功后,Maven 将会创建在 -DartifactId 中设置的名称的文件夹,对于本例来说,即 mavendemo1。该文件夹的目录如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mavendemo1
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- nowcoder
    |               `-- mavendemo1
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- nowcoder
                    `-- mavendemo1
                        `-- AppTest.java
  • src/main/java 包含项目的源代码
  • src/test/java 包含测试源代码
  • pom.xml 是项目的 Project Object Model, 即 POM。pom.xml 文件是 Maven 中项目配置的核心。它是一个单一的配置文件,其中包含以我们想要的方式构建项目所需的大部分信息。POM 文件很复杂,该项目的 POM 是:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <properties>
          <maven.compiler.source>1.7</maven.compiler.source>
          <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <dependencies>
          <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
          </dependency>
      </dependencies>
      </project>
    

同时,在家目录下将会有 .m2 文件夹储存 Maven 从仓库中下载的资源。对于 Windows 系统而言,该文件夹存储在 C:\Users$Username 目录下。

Maven 项目编译

Maven 项目的构建需要首先到该项目的目录下,即包含 pom.xml 文件的目录下,输入以下命令进行编译。

1
mvn compile

编译结果

编译成功后,项目文件夹下将会生成一个 target 文件夹,存储编译项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
target
|-- classes
|   |-- main
|   |   `-- com
|   |       `-- nowcoder
|   |           `-- mavendemo1
|   |               `-- App.class
|   |
`-- generated-sources
|   |-- annotations
|   |
`-- maven-status
    |-- maven-compiler-plugin
        `-- compile
            |-- default-compile
            |-- inputFiles.lst
  • classes 文件夹下 App.class 即编译后的 class 文件。
  • generated-sourcesmaven-status 是编译过程中自身依赖的资源

重新编译

如果希望重新编译则首先使用以下命令清除当前编译结果。

1
mvn clean

然后使用 mvn compile 命令重新编译即可。

两个命令可以结合使用。

1
mvn clean compile

即同时执行清除并重新编译。

测试项目

可以通过以下命令测试项目,即运行 test 文件夹下的测试代码。

1
mvn test

1.2 IntelliJ IDEA

IntelliJ IDEA 安装

IntelliJ IDEA 可以从 官网 进行下载安装。

IntelliJ IDEA 配置

首先,我们需要对 IDEA 的 Maven 插件进行设置。

打开 IDEA 后点击 File - Settings,点击 Build, Execution, Deployment,选择 Build Tools,选择 Maven,将 Maven home directory 修改为上一步 Maven 安装中的路径。同时,如果已经修改过 Maven settings.xml 配置文件,且希望使用该修改后配置文件,则将 User settings file 后 勾选 Override,并选择为修改后的 “settings.xml” 文件即可。

IntelliJ IDEA 中创建项目

点击 New Project 后选择 Maven,如果 Project SDK 为空,则证明IDEA 尚未配置过 Java SDK,则需要手动在 Project SDK 中选择 JDK 目录。

勾选 Create from archetype,即从原型模板创建 Maven 项目。

然后根据提示修改项目名称和存放位置等即可完成创建。

IntelliJ IDEA 中集成 Maven 的使用

在完成项目创建后,在 IDEA 界面右侧可以看到 Maven 标签,点击该标签后,在 Lifecycle 下即是可以运行的所有 Maven 命令,如 cleancompile 等等。直接双击想要执行的命令,IDEA 会自动执行。

问题

如果 IDEA 编译后提示警告:Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!

pom.xml 文件中的 properties 标签下增加如下代码即可解决(注意,properties标签不需要重复添加)。

1
2
3
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

IntelliJ IDEA 中快速构建 Maven 项目

点击菜单栏的 Build,然后点击 Build Project 即可实现自动构建 Maven 项目,效果等同于执行 mvn compile

IDEA 中构建项目的快捷键是 ctrl + F9

1.3 Spring Initializr

项目网址:https://start.spring.io/

创建 Spring Boot 项目的引导工具。帮助构建项目的基本结构,以及引用包。

底层基于 Maven,帮助我们把常用的包做一个整合。

配置

根据项目完成如下图所示的配置。

Spring Initializr.png

Dependencies 根据需要选择。

完成配置后,点击 Generate 会自动下载所选项目的 zip 压缩包。将其解压后带入 IDEA 即可使用。

测试

从 IDEA 打开项目后,进入 src->main->java->com->nowcoder->community->community 下,运行 CommunityApplication,如果控制台中出现如下输出即证明配置成功。

Spring Test.png

注意上图中蓝色部分有关 Tomcat 的输出,该输出证明 Tomcat 成功运行。这也是 Spring Boot 的优势之一,其将 Tomcat 内嵌至 Jar 包内,简化编程配置。

此外,我们可以通过在浏览器中键入 http://localhost:8080/ 来测试 Tomcat 是否运行正常。如果运行正常,浏览器将会显示 Whitelabel Error Page

2. Spring 入门

Spring Boot 核心价值(核心作用)

  1. 为项目提供起步依赖

    起步依赖简单来说就是其将实现某一个功能的很多依赖统一整合起来为单个依赖,我们仅需操作该单个依赖即可实现对该单个依赖内部定义的所有依赖的导入。

    起步依赖在 pom.xmldependencies 标签下体现。以 spring-boot-starter-thymeleaf 依赖为例,在 IDEA 中按住 ctrl 点击该依赖,可以看到其内部又定义了许多依赖,spring-boot-starter-thymeleaf 将其所需的依赖整合统一。

  2. 实现自动配置

    Spring Boot 的自动配置是应用程序启动时,Spring Boot 框架自动检测 Classpath 里的 Bean 来进行配置的一种机制。

  3. 端点监控

    Spring Boot 能够对项目的运行情况进行监控。

Spring Boot 入门示例

开发一个简单的处理客户端请求的案例,即仅输出一句话即可。

  1. src->main->java->com->nowcoder->community->community 路径下新建包 controller

  2. controller 包下新建 Java 文件 AlphaController。在该文件内输入以下代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
     package com.nowcoder.community.community.controller;
    
     import org.springframework.stereotype.Controller;
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.ResponseBody;
     // @Controller:表明该类是一个控制器,处理http请求。
     @Controller
    // @RequestMapping("/alpha"): 为该类注册一个路径 "/alpha"。
     @RequestMapping("/alpha")
     public class AlphaController {
       
         // @RequestMapping("/hello"): 为返回值为 String 的 sayHello() 方法注册一个路径 "/hello"。
         @RequestMapping("hello")
         // @ResponseBody:将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,
         // 写入到 Response 对象的 Body 区,通常用来返回 JSON 数据或者是 XML,在本例中可以理解为将
         // "Hello Spring Boot." 字符串写入到 Response 对象的 Body 区,从而实现网页上显示 "Hello Spring Boot."
         @ResponseBody
         public String sayHello() {
             return "Hello Spring Boot.";
         }
    
     }
    

    其中,”@” 开头的称为注解,本例中使用到的注解含义如下:

    • @Controller:表明该类是一个控制器,处理 HTTP 请求。
    • @RequestMapping(“/alpha”): 为该类注册一个路径 “/alpha”。
    • @RequestMapping(“/hello”): 为返回值为 String 的 sayHello 方法注册一个路径 “/hello”。
    • @ResponseBody:将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 Response 对象的 Body 区,通常用来返回 JSON 数据或者是 XML,在本例中可以理解为将 “Hello Spring Boot.” 字符串写入到 Response 对象的 Body 区,从而实现网页上显示 “Hello Spring Boot.”

重新编译程序,在浏览器中输入 http://localhost:8080/alpha/hello ,可以看到如下网页效果。

Spring Test2.png

如何修改 Tomcat 端口号

Tomcat 的默认端口号为 8080,然而有些时候该端口号可能被其他软件占用,此时有两种解决方案:

  • 修改其他软件的端口号
  • 修改 Tomcat 的端口号

此处介绍修改 Tomcat 的端口号。

Spring Boot 下,修改服务器端口,即在 src->main->resources 下修改 application.properties 文件。

在其中添加如下代码,即可修改 Tomcat 的端口号。

1
server.port = $端口号$

3. HTTP 协议

Http = HyperText Transfer Protocol,用于传输 HTML 等内容的应用层协议,规定了浏览器和服务器之间如何通信,以及通信时的数据格式。

参考学习网站:https://developer.mozilla.org/zh-CN/docs/Web/HTTP

一些重要知识点简单介绍如下。

HTTP 流

当客户端想要和服务端进行信息交互时(服务端是指最终服务器,或者是一个中间代理),过程表现为下面几步:

  1. 打开一个TCP连接:TCP连接被用来发送一条或多条请求,以及接受响应消息。客户端可能打开一条新的连接,或重用一个已经存在的连接,或者也可能开几个新的TCP连接连向服务端。

  2. 发送一个HTTP报文:HTTP报文(在HTTP/2之前)是语义可读的。在HTTP/2中,这些简单的消息被封装在了帧中,这使得报文不能被直接读取,但是原理仍是相同的。

     GET / HTTP/1.1
     Host: developer.mozilla.org
     Accept-Language: fr
    
  3. 读取服务端返回的报文信息:
     HTTP/1.1 200 OK
     Date: Sat, 09 Oct 2010 14:28:02 GMT
     Server: Apache
     Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
     ETag: "51142bc1-7449-479b075b2891b"
     Accept-Ranges: bytes
     Content-Length: 29769
     Content-Type: text/html
    
  4. 关闭连接或者为后续请求重用连接。

当HTTP流水线启动时,后续请求都可以不用等待第一个请求的成功响应就被发送。然而HTTP流水线已被证明很难在现有的网络中实现,因为现有网络中有很多老旧的软件与现代版本的软件共存。因此,HTTP流水线已被在有多请求下表现得更稳健的HTTP/2的帧所取代。

HTTP 报文

HTTP/1.1以及更早的HTTP协议报文都是语义可读的。在HTTP/2中,这些报文被嵌入到了一个新的二进制结构,帧。帧允许实现很多优化,比如报文头部的压缩和复用。即使只有原始HTTP报文的一部分以HTTP/2发送出来,每条报文的语义依旧不变,客户端会重组原始HTTP/1.1请求。因此用HTTP/1.1格式来理解HTTP/2报文仍旧有效。

有两种HTTP报文的类型,请求与响应,每种都有其特定的格式。

HTTP 请求报文

HTTP请求报文由3部分组成(请求行+请求头+请求体):

HTML请求.jpg

请求由以下元素组成:

  • 1.请求行:
    • ① 是请求方法,GET 和 POST 是最常见的 HTTP 方法,除此以外还包括 DELETE、HEAD、OPTIONS、PUT、TRACE。
    • ② 为请求对应的 URL 地址,它和报文头的 Host 属性组成完整的请求 URL。
    • ③ 是协议名称及版本号。
    • 请求行格式:请求方法 + 空格 + URL + 空格 + 协议版本 + 回车符 + 换行符
  • 2.请求头:
    • ④ 是 HTTP 的请求头,请求头包含若干个属性,格式为 “属性名:属性值”,服务端据此获取客户端的信息。与缓存相关的规则信息,均包含在header中
    • 请求头格式:头部字段名:值 + 回车符 + 换行符 ......(很多行上述内容)
  • 3.请求体:
    • ⑤ 是请求体,它将一个页面表单中的组件值通过 param1=value1&param2=value2 的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但请求体可以传递请求参数,请求URL也可以通过类似于 “/chapter15/user.html? param1=value1&param2=value2” 的方式传递请求参数。
    • 请求体即请求数据

HTTP 响应报文

HTTP 响应也由三部分组成(响应行,响应头,响应体):

HTML响应.jpg)

响应报文包含了下面的元素:

  • 1.响应行:
    • ① 报文协议及版本;
    • ② 状态码及状态描述;
  • 2.响应头:
    • ③ 响应报文头,也是由多个属性组成;
  • 3.响应体:
    • ④ 响应报文体,即我们真正要的“干货”。

查看 HTTP 请求和响应

可以使用浏览器查看某一网页的 HTTP 请求和响应。

对于 Chrome 浏览器而言,可以在网页上点击右键,选择检查,然后在 Network 标签下查看 HTTP 请求。每一条记录即一个 HTTP 请求。

Q:为什么访问一个网站有非常多的 HTTP 请求呢?

A:如下图所示,当浏览器第一次向 Web 服务器发送 HTTP 请求后,服务器会返回 HTML 文件,浏览器接收后对于该 HTML 文件进行解析。而该 HTML 文件中可能引用了其他资源,如 CSS、JS 文件等等,那么遇到每一个引用的文件,浏览器都会向服务器发送一个请求去得到该文件。因此,访问一个网站又非常多的 HTTP 请求。

HTTP请求.png

4. Spring MVC 入门

三层架构

通常我们在开发服务端代码时,将其分为三层架构,以实现解耦。

三层架构

  • 表现层
  • 业务层
  • 数据访问层

MVC.png

当浏览器发送请求访问服务器的时候,首先访问的是表现层,期待表现层向其返回数据,然后表现层会调用业务层处理业务,业务层在处理业务的过程中会调用数据层,即数据库。表现层访问业务层与业务层访问数据层可能是多次的行为。最终,表现层得到业务层处理好的数据后,进行加工返回给浏览器。

MVC

MVC 是一种设计模式,其理念是将复杂的代码分为三个层次。

  • Model: 模型层
  • View: 视图层
  • Controller: 控制层

MVC 主要解决的是三层架构中表现层的问题。

当浏览器发送请求访问服务器的时候,它访问的是 Controller,它会接收请求中的数据,并调用业务层进行处理,处理完后会得到的数据封装到 Model 中,并传给 View,然后 View 利用 Model 数据,生成 HTML,再返回给浏览器。

总而言之,Controller 负责处理浏览器请求,View 只负责渲染和展现,而它们之间联系的纽带是 Model

DispatcherServlet

Spring MVC 通过 前端控制器:DispatcherServlet 类 对 MVC 层进行调度。

DispatcherServlet 类的细节内容可以在 Spring 官网找到:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web

DispatcherServlet 类的重点内容简单介绍如下:

DispatcherServlet

Spring MVC 中所有组件都是由 DispatcherServlet 调度管理。

Web MVC Process.png

上图对请求的处理流程进行了详细解释。图中的 Front controllerDispatcherServlet

在上文中的 Spring Boot 入门示例,我们实际已经开发了一个简单的 Controller,下面我们将开发 ModelView

模板引擎

为了给浏览器返回动态 HTML,我们需要模板引擎的帮助。

模板引擎有很多,目前比较流行的是 Thymeleaf,但不管是任何模板引擎,其目的都是为了生成动态的 HTML

模板引擎.png

模板引擎需要两个元素:

  • 模板文件

    模板文件,即定义一个 HTML 模板,通过表达式将所需要的动态数据静态方式定义。只有在通过 Web 应用程序进行访问,才会显示动态页面效果,否则,显示页面的静态效果。

  • Model

    Model 即 HTML 所需要的 动态数据,在通过 Web 应用程序进行访问时,其会将模板文件中的 表达式 替换,以实现动态页面效果。

Thymeleaf

Thymeleaf 是目前主流的模板引擎,其倡导自然模板,即以 HTML 文件为模板

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<table>
  <thead>
    <tr>
      <th th:text="#{msgs.headers.name}">Name</th>
      <th th:text="#{msgs.headers.price}">Price</th>
    </tr>
  </thead>
  <tbody>
    <tr th:each="prod: ${allProducts}">
      <td th:text="${prod.name}">Oranges</td>
      <td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
    </tr>
  </tbody>
</table>

Thymeleaf 使用 th 属性赋予每个标签与后台交互的能力,当 html 文件在本地直接用浏览器打开,浏览器引擎会忽略掉 th 属性,并正常渲染页面,当把 html 文件放到服务容器访问,th 属性与后台交互,获取数据替换原先的内容,这样前端工程师在编写 html 页面时,在本地开发,正常实现页面逻辑效果即可,数据先写死,当放到服务容器时数据从后台获取。

常用语法

不管使用任何模板引擎,以下常用语法是都是学习的重点。

  • 标准表达式:解决页面上哪些地方需要被动态数据替换
  • 判断与循环:解决页面上的判断和循环逻辑
  • 模板的布局:解决复用页面上一样的区域

5. 示例

关闭 Thymeleaf 缓存

Thymeleaf 缓存默认开启,如果有缓存的情况下,对网站的访问可能是读取的旧的缓存,而非最新代码。因此,在本地环境下,建议关闭缓存,以获得最新的代码效果。而在上线后服务器环境下建议打开缓存,以降低服务器压力。

src->main->resources 下修改 application.properties 文件,加入以下代码即可。

#关闭 Thymeleaf 缓存
spring.thymeleaf.cache=false

Spring MVC 示例

首先我们知道,Spring MVC 解决的是表现层的问题,其主要有三个层次。

  • Model: 模型层
  • View: 视图层
  • Controller: 控制层

因此,本例将完成上面三个层的练习。

对于 Model 和 Controller,其代码放置于src -> main -> java -> com -> nowcoder -> community -> community -> controller 下。因为 Model 对应的类直接存在,所以不需要单独创建。

对于 View,我们使用 Thymeleaf 模板引擎,将其代码放置于 src -> main -> resources -> templates 下。

Spring MVC 示例 1:如何获取请求和响应对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.nowcoder.community.community.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

// @Controller:表明该类是一个控制器,处理http请求。
@Controller
// @RequestMapping("/alpha"): 为该类注册一个路径 "/alpha"。
@RequestMapping("/alpha")
public class AlphaController {
    /*
     * HttpServletRequest request:获取 HttpServletRequest 对象处理 HTTP 请求
     * HttpServletResponse response:获取 HttpServletResponse 对象处理 HTTP 响应
     */
    @RequestMapping("/http")
    public void http(HttpServletRequest request, HttpServletResponse response) {
        // 获取请求数据
        // 获取请求方法
        System.out.println(request.getMethod());
        // 获取请求路径
        System.out.println(request.getServletPath());
        // 获取请求行所有的 Key 迭代器,注意:请求行是 Key-Value 格式
        Enumeration<String> enumeration = request.getHeaderNames();
        // 遍历 Key 迭代器
        while (enumeration.hasMoreElements()) {
            // 获取单个 Key
            String name = enumeration.nextElement();
            // 获取请求行中该 Key 对应的 Value
            String value = request.getHeader(name);
            System.out.println(name + ": " + value);
        }
        // 获取请求体,假设传入一个 code 参数
        System.out.println(request.getParameter("code"));

        // 返回响应数据
        // 设置返回数据类型,此处设置返回 html 数据
        response.setContentType("text/html;charset=utf-8");
        // 通过 response 中封装的输出流向浏览器输出
        // 以下 try (PrintWriter writer = response.getWriter() 代表执行
        // try catch 后自动关闭 writer 流,即等同于 finally {writer.close()};
        try (PrintWriter writer = response.getWriter()) {
            // 假设向浏览器输出以下字段
            writer.write("<h1>牛客网</h1>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结而言,在 Spring MVC 中,我们使用 HttpServletRequest request 获取 HttpServletRequest 对象处理 HTTP 请求。使用 HttpServletResponse response 获取 HttpServletResponse 对象处理 HTTP 响应。

运行 “CommunityApplication” 后,浏览器输入 http://localhost:8080/alpha/http。 可以看到浏览器正常输出“牛客网”,且在 IDEA 终端中可以看到正确的输出。

HTTP测试.png

注意:输出有一行 “null” 是因为 System.out.println(request.getParameter("code")); 语句中,没有 Parameter为 “code” 的请求。为了测 试该请求,我们只需要将 URL 改为 http://localhost:8080/alpha/http?code=123 即可测试。?parameter=value 即 HTML 中添加请求体的方法, 如果要添加多个参数,可以使用 ?parameter1=value1&parameter2=value2

Spring MVC 示例 2:以更简化方式处理 GET 请求

上例中,我们使用底层方法获取 HTTP 请求,该例中,我们介绍以更简化的方式获取 HTTP 请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// @Controller:表明该类是一个控制器,处理http请求。
@Controller
// @RequestMapping("/alpha"): 为该类注册一个路径 "/alpha"。
@RequestMapping("/alpha")
public class AlphaController {
    // GET 请求:向 Web 服务器获取资源,默认方法就是 GET
    
    // GET 请求传参方式 1:/students?current=1&limit=20
    // 假设有以下路径,查询 students 数据,其支持分页显示,即 current = 1 代表当前是第 1 页
    // limit = 20 代表每页显示 20 个数据
    // /students?current=1&limit=20

    // 声明请求路径与请求方法,强制只有 GET 请求才能访问到该路径
    @RequestMapping(path = "/students", method = RequestMethod.GET)
    @ResponseBody
    // 以下方法即是简化获取参数的方法,通过在方法的形参列表中加入与请求体同名的参数,即可获取到这些参数
    // 可以通过 @RequestParam 注解对传入的参数进行进一步的细化。
    // 该例中,将 current 参数设定为:可以不传,如果不传,默认值为 1
    // 将 limit 参数设定为:可以不传,如果不传,默认值为 10
    public String getStudents(
            @RequestParam(name = "current", required = false, defaultValue = "1") int current,
            @RequestParam(name = "limit", required = false, defaultValue = "10") int limit) {
        return "current = " + current + " limit = " + limit;
    }

    // GET 请求传参方式 2:/student/1
    // 场景2:假如要根据学生 ID 查询一个学生,其路径定义为 /student/1,
    // 即将 ID = 1 编排到路径中,成为路径的一部分
    // 这种 URL 路径需要新的请求获取方式
    @RequestMapping(path = "/student/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getStudent(@PathVariable("id") int id) {
        return "Student ID: " + id;
    }
}

编译运行后,浏览器输入 http://localhost:8080/alpha/students 查看运行结果。 浏览器输入 http://localhost:8080/alpha/student/1 查看运行结果。

总之,GET 请求有两种传参的方式

  • /students?para1=value1&para2=value2
  • /student/{id}

两种不同的传参方式使用不同的注解获取参数。

Spring MVC 示例 3:以更简化方式处理 POST 请求

POST 请求:浏览器向服务器提交数据

浏览器要向服务器提交数据,首先需要打开一个带有表单的网页,通过表单填写数据后提交给服务器。

因此,我们首先需要创建一个带有表单的网页。我们创建一个简单的静态网页, 因为其是静态资源,所以应当放置于 src -> main -> resources -> static下。 在该目录下新建文件夹 html,然后新建 html 文件 student.html,其中代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>增加学生</title>
</head>
<body>
<!--    method="post" 声明该表单通过 post 请求提交数据-->
<!--    action="/alpha/student" 声明提交路径-->
<form method="post" action="/alpha/student">
    <p>
        姓名:<input type="text" name="name">
    </p>
    <p>
        年龄:<input type="text" name="age">
    </p>
    <p>
        <input type="submit" value="保存">
    </p>
</form>

</body>
</html>

编译运行后,浏览器访问 http://localhost:8080/html/student.html 即可测试静态页面是否 编写成功。

然后,我们要在 Controller 中处理该 POST 请求,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// @Controller:表明该类是一个控制器,处理http请求。
@Controller
// @RequestMapping("/alpha"): 为该类注册一个路径 "/alpha"。
@RequestMapping("/alpha")
public class AlphaController {
    // POST 请求:浏览器向服务器提交数据

    // 浏览器要向服务器提交数据,首先需要打开一个带有表单的网页,通过表单填写数据后才能提交给服务器
    // 在 resources -> static -> html 目录下定义了 student.html
    // 其中定义了 POST 提交路径:/alpha/student

    // 声明请求路径与请求方法,强制只有 POST 请求才能访问到该路径
    @RequestMapping (path = "/student", method = RequestMethod.POST)
    @ResponseBody
    // 通过在方法的形参列表中加入与表单内同名的参数,即可获取到这些参数
    public String saveStudent(String name, int age) {
        return "Name: " + name + " Age: " + age;
    }
}

编译运行后,浏览器访问 http://localhost:8080/alpha/student 测试是否处理成功。

知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 欢迎转载,并请注明来自:Yuyao 的博客 同时保持文章内容的完整和以上声明信息!