当前位置: 首页 > news >正文

04-Web后端基础(基础知识)

而像HTML、CSS、JS 以及图片、音频、视频等这些资源,我们都称为静态资源。 所谓静态资源,就是指在服务器上存储的不会改变的数据,通常不会根据用户的请求而变化。

那与静态资源对应的还有一类资源,就是动态资源。那所谓动态资源,就是指在服务器端上存储的,会根据用户请求和其他数据动态生成的,内容可能会在每次请求时都发生变化。比如:Servlet、JSP等(负责逻辑处理)。而Servlet、JSP这些技术现在早都被企业淘汰了,现在在企业项目开发中,都是直接基于Spring框架来构建动态资源。

而对于我们java程序开发的动态资源来说,我们通常会将这些动态资源部署在Tomcat,这样的Web服务器中运行。 而浏览器与服务器在通信的时候,基本都是基于HTTP协议的。

那上述所描述的这种浏览器/服务器的架构模式呢,我们称之为:BS架构

  • BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。
    • 优点:维护方便
    • 缺点:体验一般
  • CS架构:Client/Server,客户端/服务器架构模式。需要单独开发维护客户端。
    • 优点:体验不错
    • 缺点:开发维护麻烦

那前面我们已经学习了静态资源开发技术,包括:HTML、CSS、JS以及JS的高级框架Vue,异步交互技术Axios。 那那接下来呢,我们就要来学习动态资料开发技术,而动态资源开发技术中像早期的Servlet、JSP这些个技术早都被企业淘汰了,现在企业开发主流的就是基于Spring体系中的框架来开发这些动态资源。 所以,我们今天的课程内容内,分为以下四个部分:

  • SpringBootWeb入门
  • HTTP协议
  • SpringBootWeb案例
  • 分层解耦

1. SpringBootWeb入门

那接下来呢,我们就要来讲解现在企业开发的主流技术 SpringBoot,并基于SpringBoot进行Web程序的开发 。

1.1 概述

在没有正式的学习SpringBoot之前,我们要先来了解下什么是Spring。

我们可以打开Spring的官网(Spring | Home),去看一下Spring的简介:Spring makes Java simple。

Spring的官方提供很多开源的项目,我们可以点击上面的projects,看到spring家族旗下的项目,按照流行程度排序为:

Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能。而我们在项目开发时,一般会偏向于选择这一套spring家族的技术,来解决对应领域的问题,那我们称这一套技术为spring全家桶

而Spring家族旗下这么多的技术,最基础、最核心的是 SpringFramework。其他的spring家族的技术,都是基于SpringFramework的,SpringFramework中提供很多实用功能,如:依赖注入、事务管理、web开发支持、数据访问、消息服务等等。

而如果我们在项目中,直接基于SpringFramework进行开发,存在两个问题:

  • 配置繁琐
  • 入门难度大

所以基于此呢,spring官方推荐我们从另外一个项目开始学习,那就是目前最火爆的SpringBoot。 通过springboot就可以快速的帮我们构建应用程序,所以springboot呢,最大的特点有两个 :

  • 简化配置
  • 快速开发

Spring Boot 可以帮助我们非常快速的构建应用程序、简化开发、提高效率 。

而直接基于SpringBoot进行项目构建和开发,不仅是Spring官方推荐的方式,也是现在企业开发的主流。

1.2 入门程序

1.2.1 需求

需求:基于SpringBoot的方式开发一个web应用,浏览器发起请求/hello后,给浏览器返回字符串 "Hello xxx ~"。

1.2.2 开发步骤

第1步:创建SpringBoot工程,并勾选Web开发相关依赖

第2步:定义HelloController类,添加方法hello,并添加注解

1). 创建SpringBoot工程(需要联网)

基于Spring官方骨架,创建SpringBoot工程。

基本信息描述完毕之后,勾选web开发相关依赖。

SpringBoot官方提供的脚手架,里面只能够选择SpringBoot的几个最新的版本,如果要选择其他相对低一点的版本,可以在springboot项目创建完毕之后,修改项目的pom.xml文件中的版本号。

点击Create之后,就会联网创建这个SpringBoot工程,创建好之后,结构如下:

注意:在联网创建过程中,会下载相关资源(请耐心等待)

static: 存储一些静态文件(html\css\js)

templates: 存储一些模板文件

2). 定义HelloController类,添加方法hello,并添加注解

com.itheima这个包下新建一个类:HelloController

HelloController中的内容,具体如下:

package com.itheima;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController //标识当前类是一个请求处理类
public class HelloController {@RequestMapping("/hello") //标识请求路径public String hello(String name){System.out.println("HelloController ... hello: " + name);return "Hello " + name;}}

3). 运行测试

运行SpringBoot自动生成的引导类 (标识有@SpringBootApplication注解的类)

打开浏览器,输入 http://localhost:8080/hello?name=itheima

1.2.3 常见问题

大伙儿在下来联系的时候,联网基于spring的脚手架创建SpringBoot项目,偶尔可能会因为网内网络的原因,链接不上SpringBoot的脚手架网站,此时会出现如下现象:

此时可以使用阿里云提供的脚手架,网址为:https://start.aliyun.com

然后按照项目创建的向导,一步一步的创建项目即可。

1.3 入门解析

那在上面呢,我们已经完成了SpringBootWeb的入门程序,并且测试通过。 在入门程序中,我们发现,我们只需要一个main方法就可以将web应用启动起来了,然后就可以打开浏览器访问了。

那接下来我们需要明确两个问题:

1). 为什么一个main方法就可以将Web应用启动了?

因为我们在创建springboot项目的时候,选择了web开发的起步依赖spring-boot-starter-web。而spring-boot-starter-web依赖,又依赖了spring-boot-starter-tomcat,由于maven的依赖传递特性,那么在我们创建的springboot项目中也就已经有了tomcat的依赖,这个其实就是springboot中内嵌的tomcat。

而我们运行引导类中的main方法,其实启动的就是springboot中内嵌的Tomcat服务器。 而我们所开发的项目,也会自动的部署在该tomcat服务器中,并占用8080端口号 。

起步依赖:

  • 一种为开发者提供简化配置和集成的机制,使得构建Spring应用程序更加轻松。起步依赖本质上是一组预定义的依赖项集合,它们一起提供了在特定场景下开发Spring应用所需的所有库和配置。
    • spring-boot-starter-web:包含了web应用开发所需要的常见依赖。
    • spring-boot-starter-test:包含了单元测试所需要的常见依赖。
  • 官方提供的starter:https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/#using.build-systems.starters

2. HTTP协议

2.1 HTTP概述

2.1.1 介绍

HTTP:Hyper Text Transfer Protocol(超文本传输协议),规定了浏览器与服务器之间数据传输的规则。

  • http是互联网上应用最为广泛的一种网络协议
  • http协议要求:浏览器在向服务器发送请求数据时,或是服务器在向浏览器发送响应数据时,都必须按照固定的格式进行数据传输

如果想知道http协议的数据传输格式有哪些,可以打开浏览器,点击F12打开开发者工具,点击Network(网络)来查看

ps: 浏览器地址栏中发起的所有请求都是GET方式

浏览器向服务器进行请求时,服务器按照固定的格式进行解析:

服务器向浏览器进行响应时,浏览器按照固定的格式进行解析:

而我们学习HTTP协议,就是来学习请求和响应数据的具体格式内容。

2.1.2 特点

我们刚才初步认识了HTTP协议,那么我们在看看HTTP协议有哪些特点:

  • 基于TCP协议: 面向连接,安全

TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全

  • 基于请求-响应模型: 一次请求对应一次响应(先请求后响应)

请求和响应是一一对应关系,没有请求,就没有响应

  • HTTP协议是无状态协议: 对于数据没有记忆能力。每次请求-响应都是独立的

无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。

  • 缺点: 多次请求间不能共享数据
  • 优点: 速度快
  • 请求之间无法共享数据会引发的问题:
    • 如:京东购物。加入购物车和去购物车结算是两次请求
    • 由于HTTP协议的无状态特性,加入购物车请求响应结束后,并未记录加入购物车是何商品
    • 发起去购物车结算的请求后,因为无法获取哪些商品加入了购物车,会导致此次请求无法正确展示数据
  • 具体使用的时候,我们发现京东是可以正常展示数据的,原因是Java早已考虑到这个问题,并提出了使用会话技术(Cookie、Session)来解决这个问题。具体如何来做,我们后面课程中会讲到。

刚才提到HTTP协议是规定了请求和响应数据的格式,那具体的格式是什么呢? 接下来,我们就来详细剖析。

HTTP协议又分为:请求协议和响应协议

2.2 HTTP请求协议

2.2.1 介绍
  • 请求协议:浏览器将数据以请求格式发送到服务器。包括:请求行、请求头 、请求体
  • GET方式的请求协议:

  • 请求行(以上图中红色部分) :HTTP请求中的第一行数据。由:请求方式资源路径协议/版本组成(之间使用空格分隔)
    • 请求方式:GET
    • 资源路径:/brand/findAll?name=OPPO&status=1
      • 请求路径:/brand/findAll
      • 请求参数:name=OPPO&status=1
        • 请求参数是以key=value形式出现
        • 多个请求参数之间使用&连接
      • 请求路径和请求参数之间使用?连接
    • 协议/版本:HTTP/1.1
  • 请求头(以上图中黄色部分) :第二行开始,上图黄色部分内容就是请求头。格式为key: value形式
    • http是个无状态的协议,所以在请求头设置浏览器的一些自身信息和想要响应的形式。这样服务器在收到信息后,就可以知道是谁,想干什么了
    • 常见的HTTP请求头有:

请求头

含义

Host

表示请求的主机名

User-Agent

浏览器版本。 例如:Chrome浏览器的标识类似Mozilla/5.0 ...Chrome/79 ,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...)like Gecko

Accept

表示浏览器能接收的资源类型,如text/*,image/*或者*/*表示所有;

Accept-Language

表示浏览器偏好的语言,服务器可以据此返回不同语言的网页;

Accept-Encoding

表示浏览器可以支持的压缩类型,例如gzip, deflate等。

Content-Type

请求主体的数据类型

Content-Length

数据主体的大小(单位:字节)

举例说明:服务端可以根据请求头中的内容来获取客户端的相关信息,有了这些信息服务端就可以处理不同的业务需求。

比如:

  • 不同浏览器解析HTML和CSS标签的结果会有不一致,所以就会导致相同的代码在不同的浏览器会出现不同的效果
  • 服务端根据客户端请求头中的数据获取到客户端的浏览器类型,就可以根据不同的浏览器设置不同的代码来达到一致的效果(这就是我们常说的浏览器兼容问题)
  • 请求体 :存储请求参数
    • GET请求的请求参数在请求行中,故不需要设置请求体

POST方式的请求协议:

  • 请求行(以上图中红色部分):包含请求方式、资源路径、协议/版本
    • 请求方式:POST
    • 资源路径:/brand
    • 协议/版本:HTTP/1.1
  • 请求头(以上图中黄色部分)
  • 请求体(以上图中绿色部分) :存储请求参数
    • 请求体和请求头之间是有一个空行隔开(作用:用于标记请求头结束)

GET请求和POST请求的区别:

GET方式的请求数据(参数)在url请求到服务器端的

区别方式

GET请求

POST请求

请求参数

请求参数在请求行中。<br/>例:/brand/findAll?name=OPPO&status=1

请求参数在请求体中

请求参数长度

请求参数长度有限制(浏览器不同限制也不同)

请求参数长度没有限制

安全性

安全性低。原因:请求参数暴露在浏览器地址栏中。

安全性相对高

2.2.2 获取请求数据

Web服务器(Tomcat)对HTTP协议的请求数据进行解析,并进行了封装,封装到了一个对象当中(HttpServletRequest),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

代码演示如下:

@RestController
public class RequestController {/*** 请求路径 http://localhost:8080/request?name=Tom&age=18* @param request* @return*/@RequestMapping("/request")public String request(HttpServletRequest request){//1.获取请求参数 name, ageString name = request.getParameter("name");String age = request.getParameter("age");System.out.println("name = " + name + ", age = " + age);//2.获取请求路径String uri = request.getRequestURI();String url = request.getRequestURL().toString();System.out.println("uri = " + uri);System.out.println("url = " + url);//3.获取请求方式String method = request.getMethod();System.out.println("method = " + method);//4.获取请求头String header = request.getHeader("User-Agent");System.out.println("header = " + header);return "request success";}}

最终输出内容如下所示:

url: 完整的访问路径

uri:资源访问路径

2.3 HTTP响应协议

2.3.1 格式介绍
  • 响应协议:服务器将数据以响应格式返回给浏览器。包括:响应行 、响应头 、响应体

  • 响应行(以上图中红色部分):响应数据的第一行。响应行由协议及版本响应状态码状态码描述组成
    • 协议/版本:HTTP/1.1
    • 响应状态码:200
    • 状态码描述:OK
  • 响应头(以上图中黄色部分):响应数据的第二行开始。格式为key:value形式
    • http是个无状态的协议,所以可以在请求头和响应头中设置一些信息和想要执行的动作,这样,对方在收到信息后,就可以知道你是谁,你想干什么
    • 常见的HTTP响应头有:
Content-Type:表示该响应内容的类型,例如text/html,image/jpeg ;Content-Length:表示该响应内容的长度(字节数);Content-Encoding:表示该响应压缩算法,例如gzip ;Cache-Control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒 ;Set-Cookie: 告诉浏览器为当前页面所在的域设置cookie ;
  • 响应体(以上图中绿色部分): 响应数据的最后一部分。存储响应的数据
    • 响应体和响应头之间有一个空行隔开(作用:用于标记响应头结束)
2.3.2 响应状态码

状态码分类

说明

1xx

响应中 --- 临时状态码。表示请求已经接受,告诉客户端应该继续请求或者如果已经完成则忽略

2xx

成功 --- 表示请求已经被成功接收,处理已完成

3xx

重定向 --- 重定向到其它地方,让客户端再发起一个请求以完成整个处理

4xx

客户端错误 --- 处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等

5xx

服务器端错误 --- 处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等

关于响应状态码,我们先主要认识三个状态码,其余的等后期用到了再去掌握:

  • 200 ok 客户端请求成功
  • 404 Not Found 请求资源不存在
  • 500 Internal Server Error 服务端发生不可预期的错误
2.3.3 设置响应数据

Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

代码演示:

package com.itheima;import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
public class ResponseController {@RequestMapping("/response")public void response(HttpServletResponse response) throws IOException {//1.设置响应状态码response.setStatus(401);//2.设置响应头response.setHeader("name","itcast");//3.设置响应体response.setContentType("text/html;charset=utf-8");response.setCharacterEncoding("utf-8");response.getWriter().write("<h1>hello response</h1>");}@RequestMapping("/response2")public ResponseEntity<String> response2(HttpServletResponse response) throws IOException {return ResponseEntity.status(401).header("name","itcast").body("<h1>hello response</h1>");}}

浏览器访问测试:

响应状态码 和 响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头。

3. SpringBootWeb案例

3.1 需求说明

需求:基于SpringBoot开发web程序,完成用户列表的渲染展示

当在浏览器地址栏,访问前端静态页面(http://localhost:8080/usre.html)后,在前端页面上,会发送ajax请求,请求服务端(http://localhost:8080/list),服务端程序加载 user.txt 文件中的数据,读取出来后最终给前端页面响应json格式的数据,前端页面再将数据渲染展示在表格中。

3.2 代码实现

1). 准备工作:再创建一个SpringBoot工程,并勾选web依赖、lombok依赖。

2). 准备工作:引入资料中准备好的数据文件user.txt,以及static下的前端静态页面

这些文件,在提供的资料中,已经提供了直接导入进来即可。

3). 准备工作:定义封装用户信息的实体类。

com.itheima 下再定义一个包 pojo,专门用来存放实体类。 在该包下定义一个实体类User:

package com.itheima.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;/*** 封装用户信息*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String username;private String password;private String name;private Integer age;private LocalDateTime updateTime;
}

3). 开发服务端程序,接收请求,读取文本数据并响应

由于在案例中,需要读取文本中的数据,并且还需要将对象转为json格式,所以这里呢,我们在项目中再引入一个非常常用的工具包hutool。 然后调用里面的工具类,就可以非常方便快捷的完成业务操作。

  • pom.xml中引入依赖
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.27</version>
</dependency>
  • com.itheima包下新建一个子包controller,在其中创建一个UserController
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.itheima.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;@RestController
public class UserController {@RequestMapping("/list")public String list(){//1.加载并读取文件InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());//2.解析数据,封装成对象 --> 集合List<User> userList = lines.stream().map(line -> {String[] parts = line.split(",");Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).collect(Collectors.toList());//3.响应数据//return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));return userList;}}

java目录和resources两个目录下的文件在编译后最后会放在同一个目录下面,放在class目录下面,也就是放在类路径下面

4). 启动服务测试,访问:http://localhost:8080/user.html

3.3 @ResponseBody

前面我们学习过HTTL协议的交互方式:请求响应模式(有请求就有响应)。那么Controller程序呢,除了接收请求外,还可以进行响应。

在我们前面所编写的controller方法中,都已经设置了响应数据。

controller方法中的return的结果,怎么就可以响应给浏览器呢?

答案:使用@ResponseBody注解

@ResponseBody注解:

-》作用:将controller返回值直接作为响应体的数据直接响应;返回值是对象/集合->json->响应

  • 类型:方法注解、类注解
  • 位置:书写在Controller方法上或类上
  • 作用:将方法返回值直接响应给浏览器,如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器

但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解,并没有使用@ResponseBody注解,怎么给浏览器响应呢?

这是因为,我们在类上加了@RestController注解,而这个注解是由两个注解组合起来的,分别是:@Controller 、@ResponseBody。 那也就意味着,我们在类上已经添加了@ResponseBody注解了,而一旦在类上加了@ResponseBody注解,就相当于该类所有的方法中都已经添加了@ResponseBody注解。

提示:前后端分离的项目中,一般直接在请求处理类上加@RestController注解,就无需在方法上加@ResponseBody注解了。

3.4 问题分析

上述案例的功能,我们虽然已经实现,但是呢,我们会发现案例中:解析文本文件中的数据,处理数据的逻辑代码,给页面响应的代码全部都堆积在一起了,全部都写在controller方法中了。

当前程序的这个业务逻辑还是比较简单的,如果业务逻辑再稍微复杂一点,我们会看到Controller方法的代码量就很大了。

  • 当我们要修改操作数据部分的代码,需要改动Controller
  • 当我们要完善逻辑处理部分的代码,需要改动Controller
  • 当我们需要修改数据响应的代码,还是需要改动Controller

这样呢,就会造成我们整个工程代码的复用性比较差,而且代码难以维护。 那如何解决这个问题呢?其实在现在的开发中,有非常成熟的解决思路,那就是分层开发。

相关文章:

  • 网络编程中的 Protobuf 和 JsonCpp 全面解析
  • [Vue]路径跳转和路由高级设置
  • Kubernetes上的爬虫排队术——任务调度与弹性扩缩容实战
  • Qt控件:显示控件
  • Python 实现Web 请求与响应
  • SpringBoot开发——Spring Boot异常处理全攻略:五大方案实战对比
  • Redis 5.0.10 集群部署实战(3 主 3 从,三台服务器)
  • 2025年系统架构师---综合知识卷
  • webpack构建速度和打包体积优化方案
  • Qt无边框界面添加鼠标事件
  • 【推理加速】TensorRT C++ 部署YOLO11全系模型
  • 车载网关设计原则 ---- 透明性与诊断可追溯性
  • 分贝计如何帮助改善睡眠环境
  • 常见排序算法详解及其复杂度分析
  • Linux 线程(中)
  • OptiStruct结构分析与工程应用:结构激励
  • (Java基础笔记vlog)Java中常见的几种设计模式详解
  • Axure系统原型设计列表版方案
  • 构建基于全面业务数据的大数据与大模型企业护城河战略
  • 安装部署配置jenkins
  • 专做零食的网站/网站设计模板
  • 网站结构是什么 怎么做/360手机优化大师安卓版
  • 常德做网站专业公司/优化网站seo公司
  • 如何防止网站被劫持/百度关键词排名手机
  • 网站建设字体颜色代码/关键词搜索数据
  • 燕郊个人网站建设/重庆网站seo搜索引擎优化