第4章 后端Web基础(基础知识)

一、SpringBoot Web入门

静态资源:服务器上存储的不会改变的数据,通常不会根据用户的请求而变化。比如:HTML、CSS、JS、图片、视频等(负责页面展示)

动态资源:服务器端根据用户请求和其他数据动态生成的,内容可能会在每次请求时都发生变化。比如:Spring框架、已过时(ServIet、JSP)等(负责逻辑处理)

B/S架构:Browser/Server,浏览器/服务器架构模式。客户端只需浏览器,应用程序的逻辑和数据都存在服务器端。(维护方便 体验一般)

c/S架构:Client/Server,客户端/服务器架构模式。需要单独开发维护客户端。(体验不错 开发维护麻烦)

1、概述

官网:spring.io

Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能。

以Spring Framework为中心

将Spring Framework简化为Spring Boot

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

官方推荐 企业主流

2、入门程序

(1)创建项目

(2)pom.xml文件内容

目前了解即可

XML 复制代码
<!--父工程-->
<parent></parent>
​
<!--项目的坐标和描述信息-->
​
<!--Java的版本-->
<properties></properties>
​
<!--引入依赖,版本已在父工程中管理过-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
​
<!--单元测试依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webmvc-test</artifactId>
    <scope>test</scope>
</dependency>
​
<!--    SpringBoot的打包插件-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

(3)创建请求处理类

java 复制代码
package com.itheima;
​
@RestController //标识当前是一个请求处理类
public class HelloController {
​
    @RequestMapping("/hello")//请求路径
    public String hello(String name){
        System.out.println("Hello Controller ... hello : " + name);
        return "Hello " + name + "~";
    }
​
}
复制代码

浏览器访问结果

(4)启动类

java 复制代码
package com.itheima;
​
@SpringBootApplication
public class SpringbootWebQuickstartApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebQuickstartApplication.class, args);
    }
​
}

(5)整个项目的管理配置文件

resources目录下的application.properties文件

3、官方骨架连不了解决方案

将国外的地址

改为国内的阿里云的地址

使用魔法也可以

4、入门解析

起步依赖:

有starter标识

spring-boot-starter-web:包含了web应用开发所需要的常见依赖。

spring-boot-starter-test:包含了单元测试所需要的常见依赖。

官方提供的starter:Spring Boot Reference Documentation

引入web就会引入关于web开发的所有依赖。得益于Maven的参数传递

Maven引入的这两个依赖

二、HTTP协议

1、概述

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

特点:

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

2.基于请求-响应模型的:一次请求对应一次响应

3.HTTP协议是无状态的协议:对于事务处理没有记忆能力

每次请求-响应都是独立的

  • 缺点:多次请求间不能共享数据

  • 优点:速度快

2、请求协议-数据格式

(1)请求数据格式

请求头和请求体中间隔了一个空行

(2)GET和POST的区别

请求方式-GET:

请求参数在请求行中 ,没有请求体,如:/brand/findAll?name=OPPO&status=1。GET请求大小在浏览器中是有限制的

请求方式-POST:

请求参数在请求体中 ,POST请求大小是没有限制的。

(3)请求头中的key介绍

Host:请求的主机名

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

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

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

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

Content-Type:请求主体的数据类型 。 Content-Length:请求主体的大小(单位:字节)。

3、请求协议-请求数据获取

Web服务器(Tomcat)对HTTP协议的请求数据进行解析 ,并进行了封装 (HttpServletRequest),在调用Controller方法的时候传递给了该方法。

这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

java 复制代码
@RestController
public class RequestTestController {
​
    @RequestMapping("/request")
    public String request(HttpServletRequest request){
        // 1.获取请求参数name, age
        String name = request.getParameter("name"); // Tom
​
        // 2.获取请求路径uri 和 url
        String uri = request.getRequestURI(); // /request
        String url = request.getRequestURL().toString(); // http://localhost:8080/request
​
        // 3.获取请求头 User-Agent
        String userAgent = request.getHeader("User-Agent"); // Mozilla/5.0 (Windows NT 10.0; Win64; x64)
​
        // 4.获取请求方式
        String method = request.getMethod(); // GET
​
        // 5.获取请求的查询字符串
        String queryString = request.getQueryString(); // name=Tomcat&age=10
​
        return "request success";
    }
}

小结:

1.HTTP请求数据需要程序员自己解析吗?

不需要,Web服务器负责对HTTP请求数据进行解析,并封装为了请求对象

2.如何获取请求数据?

HttpServletRequest对象里面封装了所有的请求信息

4、响应协议-数据格式

(1)响应数据格式

(2)五类状态码

状态码大全:状态 | Status - HTTP 中文开发手册 - 开发者手册 - 腾讯云开发者社区-腾讯云

(3)响应体的key介绍

5、响应协议-响应数据设置

Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),并在调用Controller方法的时候传递给了该方法。

这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

方式一、HttpServletResponse原生写法

java 复制代码
@RestController
public class ResponseController {
​
    @RequestMapping("/response")
    public void response(HttpServletResponse response) throws IOException {
        // 1.设置响应状态码
        response.setStatus(401);
        // 2.设置响应头
        response.setHeader("itheima", "itheima");
        // 3.设置响应体
        response.getWriter().write("<h1>Hello Response</h1>");
    }
}

方式二:ResponseEntity封装写法(Spring推荐)

java 复制代码
@RestController
public class ResponseController {
​
    @RequestMapping("/response")
    public ResponseEntity<String> response() {
        return ResponseEntity.status(401)       // 1.设置响应状态码
                .header("group", "itcast")       // 2.设置响应头
                .body("<h1>Hello Response</h1>");// 3.设置响应体
    }
}

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

三、SpringBoot Web案例

1、准备工作

创建一个SpringBoot工程,并勾选web依赖、lombok。

引入资料中准备好的用户数据文件(user.txt),及前端静态页面。

定义一个实体类,用来封装用户信息

2、开发服务端程序

接收请求,读取文本数据并响应。

3、具体操作流程

(1)创建项目

勾选两项,并Create创建,没用的文件删掉

(2)引入数据和静态文件

(3)定义实体类

数据类型用包装类,不要用基本数据类型,因为基本数据类型要赋初始值

在资源文件夹下创建pojo文件夹,创建User实体类

java 复制代码
@Data//代替set、get方法
@NoArgsConstructor//代替无参构造
@AllArgsConstructor//代替有参构造
public class User {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Integer age;
    private LocalDateTime updateTime;
}

(4)整体项目

加载hutool依赖,用于加载并读取txt文件

XML 复制代码
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.27</version>
</dependency>

创建控制层文件

在UserController文件中,操作文件,将文件内容拆分

@ResponseBody注解的作用

  • controller方法的返回值直接写入HTTP响应体
  • 如果是对象或集合 ,会先转为json,再响应
  • @RestController = @Controller +@ResponseBody
java 复制代码
@RestController
public class UserController {
​
    @RequestMapping("/list")
    public List<User> 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.响应数据
        //得益于@RestController注解
        return userList;
    }
}

以上代码复用性差、难以维护

四、分层解耦

用于解决以上代码复用性差、难以维护的问题

1、三层架构

将以上代码拆解成这三层

(1)每一层的职责

controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。

service:业务逻辑层,处理具体的业务逻辑。

dao:数据访问层(Data AccessObject)(持久层),负责数据访问操作,包括数据的增、删、改、查。

(2)创建三层架构

创建controller文件夹、创建service文件夹、创建dao文件夹

在dao数据访问层创建接口和实现类

在service业务层创建接口和实现类

将以上单文件中的代码分解到这些分层的文件中

2、解耦思路(IOC与DI介绍)

(1)内聚与耦合

耦合:衡量软件中各个层/各个模块的依赖关联程度。

内聚:软件中各个功能模块内部的功能联系。

软件设计原则:高内聚低耦合。

高耦合的原因:每一层都new其它层的对象

降低高耦合:创建一个容器,用于装每一层产生的对象,其他层在容器中调用该对象。

用到的技术包括控制反转和依赖注入

(2)分层解耦的思路

控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

Bean对象:lOC容器中创建、管理的对象,称之为Bean。

3、IOC与DI入门

将Dao及Service层的实现类,交给IOC容器管理。

为Controller及Service注入运行时所依赖的对象。

在Dao及Service层实现类上面加@Component注解,表示交给了IOC容器管理(注意是加在实现类上,而不是接口上)

在Controller及Service层实现类下面加@Autowired注解,表示从DI容器中获取了对象

4、IOC详解

(1)其他控制反转的注解

除了使用@Component注解,交给IOC容器还提供了其他三个注解

注意: 声明bean的时候,可以通过注解的value属性 指定bean的名字 ,如果没有指定,默认为类名首字母小写

@RestController已经包含了@Controller

(2)组件扫描注解

前面声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描。

该注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication中 ,默认扫描的范围是启 动类所在包及其子包

规范:启动类裸露在外面

5、DI详解一

常见的依赖注入方式

(1).属性注入

企业常用

(2).构造函数注入

(3).setter注入

6、DI详解二

@Autowired注解,默认是按照类型进行注入的。

如果存在多个相同类型的bean,将会报出如下错误:

(1)方案一:@Primary

加在被注入的类上。用于提高优先级

(2)方案二:@Qualifier

加载注入的类上,表示选择哪个类注入

(3)方案三:@Resource

将方案二的两个注解合并为一个注解

@Resource与@Autowired区别?

@Autowired是Spring框架 提供的注解,而@Resource是JavaEE规范提供的

@Autowired默认是按照类型 注入,而@Resource默认是按照名称注入

相关推荐
芷栀夏1 小时前
Java教育平台实战复盘:课程、考试与学习行为分析系统设计
java·开发语言·学习
从零开始的代码生活_1 小时前
C++ 多态详解:虚函数、动态绑定、抽象类与虚表原理
开发语言·c++·后端·学习·算法
xywww1681 小时前
AWS 账号权限怎么分:根用户和 IAM 用户区别及日常使用建议
大数据·开发语言·人工智能·python·gpt·云计算·aws
维基框架2 小时前
维基框架(Wiki-Framework) 1.2.0:Mybatis 升级为主从读写分离
java·后端·架构
Memory_荒年2 小时前
Java函数式接口:把代码变成“拼乐高”的快乐,你体验过吗?
java
Memory_荒年2 小时前
WebSocket:让服务器学会“主动搭讪”的黑科技
java
Henrii_历小海2 小时前
WhatsApp Business API 2026 计费架构重构:从“对话计费“到“按消息计费“的技术实现与工程应对
java·重构·架构
炸薯条!2 小时前
从零开始学C++ (内存管理)
java·jvm·c++
许彰午3 小时前
100_Python面试常见问题汇总
java·python·面试