一、springboot介绍

现在的项目基本都是基于springboot来开发的,springboot就是简单化的spring框架。

1.1 简单的springboot应用

以前创建Java的普通项目模块时,如图:

现在创建springboot,如图:

之后next---------选版本都可以,就是不选快照版本------------依赖项选择web spring。
左侧进行删除,只剩这几个部分:如图:

打开该springboot的项目模块,发现:

父工程,version是springboot的版本,下面是该模块的坐标。这个pom.xml不用改动。

- 并且,main下面的java包下面有一个启动类,就是用来启动项目的,当该项目模块写好后,就可以运行这个启动类,来运行整个项目。
- **static包里面是静态资源,是HTML、CSS、JS等。**templates是模板。下面的application.properties是配置文件。
前面说:浏览器访问网页,都是从tomcat这个web服务器请求网页的,现在电脑上没有安装tomcat,为什么依旧能运行呢?

起步依赖,会将tomcat服务器内嵌进来,这个main方法运行后,将启动内嵌进来的TomCat服务器,会将我们所编写的项目代码部署在这个tomcat服务器当中,之后就可以用浏览器来访问所制作的页面。

所以我们不用在电脑上单独安装tomcat服务器,因为有起步依赖,已经将tomcat服务器内嵌进来了。
代码示例:
java
package com.itheima.springbootquickstart;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class helloProject {
@RequestMapping("/hello")
public String hello(String name){
System.out.println("hello"+name);
return "hello,"+name+"~";
}
}
name形参接收的就是搜索的网址上写的name值。return 返回的是网页中会显示的字符。
输出结果:

类的注解(处理请求)和方法的注解(请求路径)一定要写,方法的注解requestmapping(" "),括号里面写网址信息,代表:这个方法要处理哪一个网址的请求。。
1.2 HTTP协议



1.2.1 HTTP请求协议
请求数据格式




服务器是如何获取请求数据的?

把浏览器发送来的请求数据都封装在了HttpServletRequest这个类的某个对象中,并把这个对象传递给了请求处理类中的方法,供这些方法调用。
代码示例:




1.2.2 HTTP响应协议
响应数据

状态码

1)状态码3XX:重定向解释:
一开始浏览器向A 请求资源,但是资源不在A服务器,所以A响应 "3XX"状态码来重定向,浏览器就去B服务器去找资源,最后得到资源。



2)状态码404解释:找一个不存在的网页资源。
因为在本机并没有创建一个/request2的请求处理类,所以会返回404:找不到资源。

3)"状态码500"解释------服务器端错误
让服务器端的请求处理类的代码发生错误。



4)这三个状态码要掌握

响应头


响应数据设置


方式一:

**理解:**响应数据是自己写的,因为我们现在写的代码就是web服务器里面要存储的资源,我们现在就是服务器,在浏览器上访问对应网址,返回什么内容,由我们写的getwrite.write()方法来实现。
**问题:****两个请求处理类的请求地址一样,如果运行启动类了,会不会两个类的方法都运行?**比如及获取请求数据、简单的hello案例?
------------答案:不能,每个请求处理类中的方法的请求地址都不能一样,因为如果一样了,那就不知道调用哪个方法了。
输出结果:


方式二:

输出结果:

响应数据总结:

二、Springboot简单案例

代码:
要利用糊涂包这个依赖来使用工具,便捷地读取文件中的数据
请求处理类:
java
package com.itheima;
import cn.hutool.core.io.IoUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@RestController
public class collol {
@RequestMapping("/list")
public List<User> list() throws FileNotFoundException {
//1.要先把user.txt的文档数据给读取到一个集合当中list
//先得到user.txt的输入流
InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> list = IoUtil.readLines(in, "utf-8", new ArrayList<>());
//2.把list集合中的数据变为user类的对象,进行封装
//用stream流
List<User> userlist = list.stream().map(u -> {
String[] str = u.split(",");
System.out.println(str);
Integer id = Integer.parseInt(str[0]);
String username = str[1];
String password = str[2];
String name = str[3];
Integer age = Integer.parseInt(str[4]);
LocalDateTime updateTime = LocalDateTime.parse(str[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new User(id, username, password, name, age, updateTime);
}).collect(Collectors.toList());
System.out.println(userlist);
return userlist;
}
}
User类:
java
package com.itheima;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
private LocalDateTime updateTime;
public User(Integer id, String username, String password, String name, Integer age, LocalDateTime updateTime) {
this.id = id;
this.username = username;
this.password = password;
this.name = name;
this.age = age;
this.updateTime = updateTime;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
", updateTime=" + updateTime +
'}';
}
/**
* 获取
* @return id
*/
public Integer getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
/**
* 获取
* @return updateTime
*/
public LocalDateTime getUpdateTime() {
return updateTime;
}
/**
* 设置
* @param updateTime
*/
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
}
用lombok注解的User类:
java
package com.itheima;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
private LocalDateTime updateTime;
}
前端:

前端使用ajax请求的地址/list 要和请求处理类的requestMapping的地址一样。
注:lombok注解无法使用,用的ptg成功了。之后把ptg删了,又用的注解,又成功了!???
运行结果:

总结:

三、分层解耦
3.1 三层架构

代码:
代码目录以后都这样写:
一个包里面先写接口--------再写实现类的包impl---------再写实现类XXXImpl。


java
package com.itheima.service.impl;
import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
public class UserServiceImpl implements UserService {
private UserDao userDao=new UserDaoImpl();
@Override
public List<User> findAll() {
List<String> list = userDao.findAll();
//2.把list集合中的数据变为user类的对象,进行封装
//用stream流
List<User> userlist = list.stream().map(u -> {
String[] str = u.split(",");
System.out.println(str);
Integer id = Integer.parseInt(str[0]);
String username = str[1];
String password = str[2];
String name = str[3];
Integer age = Integer.parseInt(str[4]);
LocalDateTime updateTime = LocalDateTime.parse(str[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new User(id, username, password, name, age, updateTime);
}).collect(Collectors.toList());
return userlist;
}
}
java
package com.itheima.service;
import com.itheima.pojo.User;
import java.util.List;
public interface UserService {
public List<User> findAll();
}
java
package com.itheima.controller;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserControl {
private UserService userService=new UserServiceImpl();
@RequestMapping("/list")
public List<User> list(){
List<User> userlist = userService.findAll();
return userlist;
}
}
访问顺序图:

拆分前后对比:

总结:

3.2 分层解耦

controller和service之间通过创建对象,调用对象的方法来关联(耦合),为了以后在更新类service时,改动代码不那么复杂,就开始了解耦。

解耦的方法是:不在原来的地方new XXX来创建对象,调用对象方法。而是:
- 控制反转IOC:把创建对象的控制权由程序的new 类名------>>>由IOC容器创建。
- 依赖注入DI:容器为程序提供其运行时所需要的对象。
- Bean对象:IOC容器内的对象就是Bean对象。
3.3 分层解耦代码实现


代码:
UserDaoImpl类 和 UserServiceImpl类 上面加一个注解@component
原来new 对象的成员变量上面加一个注解@Autowired



3.4 IOC详解

- 控制层、业务层和数据访问层的IOC注解都不一样,要规范使用。
- 控制层的@resControl注解已经包含了@Controller注解,不用再写了。

所以在写web应用时,一定要注意模块代码的结构:启动类一定要在com.itheima下面。这样才能扫描IOC的四大注解。这些IOC的注解(把类的对象都放到容器中)才能生效。

3.5 DI详解
需要使用对象的时候,用到@Autowired给成员变量。
DI要做的就是给类的成员变量赋值,只不过这个成员变量不是基本数据类型,而是我们自己定义的业务逻辑类、数据访问类等。所以,我们的目的是让 对象类型的成员变量被赋值。
一般情况下,给成员变量赋值有三种方法:1)直接赋值-------属性注入 2)构造方法赋值-------构造函数注入 3)set方法赋值---------setter注入
IOC容器里都是各种类型的对象值,DI要做的就是把对应类型的对象值捞出来,通过这三种方法的其中一种给成员变量赋上值。
常用的是 属性注入 和 构造函数注入。90%的项目用属性注入,因为代码简单;构造函数注入更加规范。setter注入很少用。

代码示例:
构造方法注入

setter注入

3.5.1 DI注意事项

当存在多个相同接口类型的实现类时,此时IOC容器有多个相同类型的对象,直接运行会报错。
有以下三个方法来解决:@primary @Qualifier @Resource
@primary:


@Qualifier:


理解:

- return返回的是前端ajax请求所需要的数据,因为有RestController注解,所以响应给前端的数据就会自动变成json格式给前端。
- 后端启动类的这些代码,其实就是与数据库交互数据、指令来完成前端的需要。
- 前端可以通过浏览器直接打开,但是后端必须要启动类启动之后,被动地等待前端的请求才能返回数据。