一、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默认是按照名称注入