目录
1). 将Service及Dao层的实现类,交给IOC容器管理
2). 为Controller 及 Service注入运行时所依赖的对象
1.Spring概念:
Spring是多个框架的集合,一种生态圈
提供了非常多的子项目 用于解决不同的问题
SpringBoot 是 spring 提供的 用于快速构建 spring项目的一个子项目
spring freamwork 是 spring 众多子项目 中的 基础核心项目
2. spring程序快速入门:
在点击 creat创建项目之后
会自动生成 开始 类
自定义一个请求处理类:
spring框架会根据注解 和 tocat用tcp传输 socket接受到的 值做比较 如果 根据反射创造 请求类
如果请求类中 方法上注解的值 和 socket 接受到的值一样 则 利用反射 执行这个方法
3.HTTP协议:
特点:
基于TCP 协议:
基于请求响应模型:
相应和请求时一一对应的
HTTP协议是无状态协议:
对于数据没有记忆功能 每次请求-相应都是独立的
请求协议:为浏览器向服务器发出的消息
只有post请求才有请求体
get 的请求参数在请求行中
-
GET方式的请求协议:
POST方式的请求协议:
举例说明:服务端可以根据请求头中的内容来获取客户端的相关信息,有了这些信息服务端就可以处理不同的业务需求。
比如:
不同浏览器解析HTML和CSS标签的结果会有不一致,所以就会导致相同的代码在不同的浏览器会出现不同的效果
服务端根据客户端请求头中的数据获取到客户端的浏览器类型,就可以根据不同的浏览器设置不同的代码来达到一致的效果(这就是我们常说的浏览器兼容问题)
-
请求体 :存储请求参数
-
GET请求的请求参数在请求行中,故不需要设置请求体
-
获取请求数据:
url 统一资源定位符: 需要通过该符号定位到网络上唯一的资源
uri 统一资源表示符: 可以标识某台服务器中唯一的资源
当tomcat接收到浏览器的请求后, 会把请求消息解析, 并封装到一个HttpServletRequest对象中, 反射执行方法时,会自动传入
@RestController
public class RequestController {
/**
* 请求路径 http://localhost:8080/request?name=Tom&age=18
* @param request
* @return
*/
@RequestMapping("/request")
public String request(HttpServletRequest request){
//1.获取请求参数 name, age
String 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";
}
}
响应协议:为服务器向浏览器发出的消息
-
响应协议:服务器将数据以响应格式返回给浏览器。包括:响应行 、响应头 、响应体
相应状态码:
4xx 为客户端 访问资源不存在 客户端问题
5xx 为服务端抛出异常 服务端问题
200 为客户端请求成功
响应状态码 和 响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头。
4.Spring 三层架构:
@RestController 由两个注解组成 @Controller 、@ResponseBody
@Controller 为标识 这个 类是 一个请求处理的类
@ResponseBody: 返回的内容可以根据请求的 Accept 头自动转换为 JSON、XML 等不同格式的数据
三层架构:
controller :控制层: 接受请求, 给出响应
service :业务层: 处理业务逻辑
dao :数据层: 文件/数据库的操作
controller层:
@RestController
//包含 @Controller 和 @ResponseBody
public class UserController {
@Autowired
private UserSerivice userSerivice;
@RequestMapping("/list")
public List<User> list(HttpServletRequest request){
String name = request.getParameter("name");
System.out.println(name);
String age = request.getParameter("age");
System.out.println(age);
List<User> finalList = new ArrayList<>();
List<User> collect = userSerivice.list();
if ((name==null)||(name.equals(""))&&((age==null) || age.equals(""))){
finalList = collect;
}else if ((name != null)&&(age == null || age.equals(""))){
finalList = collect.stream().filter((user) -> user.getName().equals(name)).collect(Collectors.toList());
} else if ((name == null || name.equals(""))&&(age != null)) {
finalList = collect.stream().filter((user) -> user.getAge() == Integer.parseInt(age)).collect(Collectors.toList());
}else{
finalList = collect.stream().filter((user) -> user.getName().equals(name)&&user.getAge() == Integer.parseInt(age)).collect(Collectors.toList());
}
return finalList;
}
}
service层:
//@Component 或 @Service 都可以
@Service
public class UserServiceImpl implements UserSerivice{
@Autowired
UserDao users;
@Override
public List<User> list() {
List<String> list = users.list();
List<User> collect = list.stream().map((s) -> {
String[] split = s.split(",");
User user = new User(Integer.parseInt(split[0]), split[1], split[2], split[3], Integer.parseInt(split[4]), LocalDateTime.parse(split[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return user;
}).collect(Collectors.toList());
return collect;
}
}
dao层:
//@Component 或 @Repository 都可以
@Repository
public class UserDaoImpl implements UserDao {
@Override
public List<String> list() {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> strings = IoUtil.readLines(resourceAsStream, "UTF-8", new ArrayList<>());
return strings;
}
}
classLoader.getResource() 默认从类路径下获取内容 类路径为:java文件夹下的和resources文件夹下的
getResourceAsStream()可以得到一个文件或网络的 输入流对象
url :获取的为文件的绝对路径 在请求协议的 获取相应数据中url可以 定位到 网络上的唯一资源
hutool:
IoUtil 为hutool 工具包下的类
hutool的 坐标为:
IoUtil.readLines(输入流,编码格式,Collection集合) :可以一起读取多行数据
Collection 为单链集合 包括 list 和 set 接口
https://blog.csdn.net/moskidi/article/details/143693695?spm=1001.2014.3001.5501
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.27</version>
</dependency>
IOC & DI :
把三层架构中的每一层进行结构 sercvice层需要数据时之间 从 容器中 获取dao对象
controller 需要获取 结果时 从 容器中创建 service对象
IOC容器中的对象 被称为 been对象
1). 将Service及Dao层的实现类,交给IOC容器管理
在实现类加上 @Component
注解,就代表把当前类产生的对象交给IOC容器管理。
2). 为Controller 及 Service注入运行时所依赖的对象
@Autowired 为自动 在容器中寻找对应对象 并且依赖注入
替代方式:
那么此时,我们就可以使用 @Service
注解声明Service层的bean。 使用 @Repository
注解声明Dao层的bean。
@RestController 中已经包含了@Controller
注意:
明bean的时候,可以通过注解的value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
组件扫描:
使用前面学习的四个注解声明的bean不一定会生效 bean想要生效,还需要被组件扫描
注意 : 默认扫描的 范围时 启动类 所在的包 及其子包
DI详解:
@Autowired 进行依赖注入,常见的方式,有如下三种:
1). 属性注入(使用的最多)
-
优点:代码简洁、方便快速开发。
-
缺点:隐藏了类之间的依赖关系、可能会破坏类的封装性。
2). 构造函数注入
-
注意:如果只有一个构造函数,@Autowired注解可以省略。(通常来说,也只有一个构造函数)
3). setter注入
IOC 中存在多个类型相同的 bean 对象的问题:
那如果在IOC容器中,存在多个相同类型的bean对象,会出现什么情况呢?
如何解决上述问题呢?Spring提供了以下几种解决方案:
-
@Primary
-
@Qualifier
-
@Resource
方案一:使用@Primary注解
当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
有多个UserService 类型的 bean 是 可以 用 @Primary 来 指定注入的bean 对象
@Primary
@Service
public class UserServiceImpl implements UserService {
}
方案二:使用@Qualifier注解
指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用。
在DI 注入 时 可以用@Qulifier 指定注入 bean 的名称
@RestController
public class UserController {
@Qualifier("userServiceImpl")
@Autowired
private UserService userService;
方案三:使用@Resource注解
是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
注意:@Resource 注解 由 jdk 提供 而不是spring
注解中没有 value 属性名 所以需要 用 name = 指定 属性值
@RestController
public class UserController {
@Resource(name = "userServiceImpl")
private UserService userService;
面试题:@Autowird 与 @Resource的区别
-
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
-
@Autowired 默认是按照类型注入,而@Resource是按照名称注入