starter-web:实现Web场景开发,提供了嵌入的Tomcat以及Spring MVC的依赖。
starter-thymeleaf:前后端不分离的页面渲染。与Spring MVC等Web框架进行集成作为Web应用的模板引擎。能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。
开发时使用,生产环境不用
功能:
代码变更后应用会自动重启(需要借助 IDE 的自动编译,局部重启,只重启修改过的)
当面向浏览器的资源(如模板、JavaScript、样式表)等发生变化时,会自动刷新浏览器
LiveReload server is running on port 35729
自动禁用(页面渲染的)模板缓存
如果使用 H2 数据库,则内置了 H2 控制台。访问:http://localhost:8080/h2-consle
也称为版本控制(version control)系统,常用工具有:GitLab、SVN(Subversion)、Bitbucket 等;
需纳入版本控制的有:功能代码、测试代码、测试脚本、构建脚本、部署脚本、配置文件等;
index是暂存区,通过add添加
commit:从暂存区到本地仓库
依赖注入(Dependency Injection),又叫控制反转(IoC)
依赖注入:创建对象实例时,为这个对象注入属性值或其它对象实例
依赖于容器注入它所需要的外部资源
依赖的是接口,而不是实际的new对象。为了好修改,类不必修改。
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
@Component
通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中
@ComponentScan
注解定义要扫描的路径从中找出标识了需要装@Bean
注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean
告
诉了 Spring 这是某个类的实例,当我们需要用它的时候还给我。
@Component
(和@Service
和@Repository
)用于自动检测和使用类路径扫描自动配置bean。注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。
@Bean
用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许精确地创建和配置bean。
管理Bean分为注册和装配Bean两部分。完成管理Bean任务有以下三种方式:
@Component注解:告诉Spring有可能会创建类的实例,接口的实现(在上下文中创建对象)
@ComponentScan注解:明确告诉Spring在当前类对应的包和相应的子包中搜索Component,如果有就自动创建实例对象
@Configuration注解:告诉Spring类要做配置,用ComponentScan组装
@Configuration
@ComponentScan
public class CDPlayerConfig {
//配置类,告诉Spring组装的入口
//ComponentScan可以加参数,告诉去哪里搜
}
@Autowired:把上下文中的另一个对象注入到当前类中,建立依赖关系。
用在构造器
@Autowired
public CDPlayer(CompactDisc cd) {
this.cd = cd;
}
用在setter方法
@Autowired
public void setCd(CompactDisc cd) {//右键generate setter
this.cd = cd;
}
直接加在私有成员
@Autowired
private CompactDisc cd;
使用@Bean注解,并创建new对象
@Configuration注解:告诉Spring类要做配置,用ComponentScan组装
/**
* cdplayer配置
* 配置类的用途就是生成并注入 Bean
*/
@Configuration
public class CDPlayerConfig {//Spring的入口
@Bean//告诉Spring来调这个方法,怎么来new是程序员自己考虑
public CompactDisc compactDisc() {
return new SgtPeppers();
}
// @Bean//需要参数,Spring会自动在上下文找是否实现了这个接口的对象,找CompactDisc的实例(加不加Autowired效果都一样)
// public CDPlayer cdPlayer(CompactDisc cd) {
// return new CDPlayer(cd);
// }
@Bean//不是new了一个对象,而是获得上下文的对象的引用 不是应用代码!因为使用了 @Configuration 和 @Bean 注解,多次调用该方法也不会多次 new
public CDPlayer cdPlayer() {
return new CDPlayer(compactDisc()) ;
}
}
通过xml告诉bean组装的意图
<bean id="compactDisc" class="soundsystem.SgtPeppers" />
<bean id="cdPlayer" class="soundsystem.CDPlayer">
<constructor-arg ref="compactDisc" />
</bean>
可以通过改class,指定整合的内容,匹配compactDisc接口;相互之间并不是直接关联的
@Scope
可以与 @Component
和 @Bean
一起使用,指定作用域
Singleton
,单例,不使用 @Scope
时默认,在整个应用中,只创建 bean 的一个实例Prototype
,原型,每次注入或者通过 Spring 应用上下文获取的时候,都会创建一个新 bean 实例Session
,会话,在 Web 应用中,为每个会话创建一个 bean 实例
Request
,请求,在 Web 应用中,为每个请求创建一个 bean 实例
使用会话和请求作用域,重定义的话用@Scope
@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart(){
}
默认是Singleton
@Before:指在perform()之前,调用silenceCellPhones()
@Aspect切面类中有很多advice。@Before是一个advice,里面是切点表达式。一个before/after就是一条advice。
@Aspect具有@Component的效果吗?没有!Spring扫描不到不会实例化
要么在Audience类前加@Component,在config类前加@ComponentScan
@Controller、@Service、@Repository具有@Component的效果
定义切面类Audience.java @Aspect 很多advice
@Aspect//提示这是一个切面!
public class Audience {
@Before("execution(* concert.Performance.perform( .. ))")//包路径.接口.方法 ..表示不在意参数有多少个 *表示不关心返回值是什么
//在被切入的方法调用之前,把当前方法逻辑执行
//这里指在perform()之前,调用silenceCellPhones()
public void silenceCellPhones() {
System.out.println("Silencing cell phones");
}
@Before("execution(* concert.Performance.perform( .. ))")
public void takeSeats() {
System.out.println("Taking seats");
}
@AfterReturning("execution(* concert.Performance.perform( .. ))")
//在perform()方法正常返回的时候切入
public void applause() {
System.out.println("CLAP CLAP CLAP!!!");
}
@AfterThrowing("execution(* concert.Performance.perform( .. ))")
//在perform()方法异常时切入
public void demandRefund() {
System.out.println("Demand a refund");
}
}
在config中将切面的实例化
@Configuration
@EnableAspectJAutoProxy //开启AspectJ的自动代理机制 提醒要用切面,对有切面需求的对象引用都使用代理
public class ConcertConfig {//配置类,用于实例化bean
@Bean
public Performance concert() {
return new Concert();
}
// @Bean
// public Performance concert2() {
// return new Concert();
// }
@Bean
public Audience audience() { //定义Audience的bean
return new Audience();
}
@Bean//需要实例化!
public EncoreableIntroducer encoreableIntroducer() {
return new EncoreableIntroducer();
}
或者在Audience类前加Component,在config类前加ComponentScan
加入注解@EnableAspectJAutoProxy,提醒要用切面,对有切面需求的对象引用都使用代理
用来限定连接点满足某些条件,如限定参数、包路径、bean名称
lombok可以简化java代码的书写:编译时,lombok帮助填写我们没填的代码
如使用@Data,lombok会帮忙生成get/set/equals/hashCode
要装插件,否则省略很多内容后会报错
注解 | 描述 |
---|---|
@RequestMapping |
通用的请求处理,一般只在类级别使用 |
@GetMapping |
处理 HTTP GET 请求 |
@PostMapping |
处理 HTTP POST 请求 |
@PutMapping |
处理 HTTP PUT 请求 |
@DeleteMapping |
处理 HTTP DELETE 请求 |
@PatchMapping |
处理 HTTP PATCH 请求 |
@RequestMapping:既可以加在方法上,也可以加在类上
@SpringBootApplication:指明程序的入口
进入控制器层:进行参数解析
客户端请求参数分类:
@PathVariable
@RequestParam
@Valid
校验json
请求体,应用于前后端分离的场景,使用 @RequestBody
把 json
格式转成 java 对象;@ResponseBody
,把 java 对象转成 json
格式进入业务层:做数据持久化,访问数据访问层
控制器层拿到返回值后怎么处理?
前后端不分离时:客户端请求页面,所以返回时将model的属性作为页面渲染的属性,返回视图名,通过第三方页面渲染返回页面(如thymeleaf)
前后端分离时:请求JSON格式。加@ResponseBody,指需要将java对象变成json。每个方法上面写很麻烦,在类上面写@RestController
特点 | JdbcTemplate | Spring Data JDBC | JDA |
---|---|---|---|
实现具体类(Repository.java) | 需要 | 不需要,只要写明继承关系 | 不需要,只要写明继承关系 |
定义实体类和数据库表的映射关系 | 不需要 | 需要 | 需要 |
程序员维护表之间的关系 | 需要 | 不需要 | 不需要 |
显式提供表结构(建表 SQL 脚本) | 需要 | 需要 | 不需要,可以自动推断 |
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
private JdbcTemplate jdbcTemplate;//模板 加了starter-jdbc依赖后,会帮忙写,只需提供变化的部分
特点:
解决样板式代码的问题(重复性),只需要提供查询逻辑。
update
、execute
、query
等。可以帮忙完成重复性代码。需要实现具体类 JdbcIngredientRepository
而其他两种方法不用;
需要提供 src/main/resources/schema.sql
文件作为表结构的定义(建表脚本)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
特点:
需要定义实体类和数据库表的映射关系;
需要@Table、@Id、@Column等注解
@Data//lombok会帮忙生成get/set/equals/hashCode
//@Table("mytable")//可以将当前的java对象对应到数据库的哪一张表
@Table //如果不写,或者只写@Table,当前Ingredient对象就对应数据库中的Ingredient表
@AllArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
public class Ingredient implements Persistable<String> {
@Id
private String id;
private String name;
private Type type;
@Override
public boolean isNew() {
return true;
}
public enum Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
不需要实现具体类,只需要写好继承关系
需要提供 src/main/resources/schema.sql
文件作为表结构的定义(建表脚本)。
加devtools依赖包:默认提供h2-console的访问,就可以及时验证数据库开发的结果
开发流程:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
定义实体类和数据库表的对应关系
特征:
与JDBC的共同点:定义接口、定义对应关系
定义查询方法,无需实现:
List<TacoOrder> findByDeliveryZip( String deliveryZip );
声明自定义查询(JDQL 面向对象查询语言):
不符合方法命名约定时,或者命名太长时
@Query("Order o where o.deliveryCity = 'Seattle'")
List<TacoOrder> readOrdersDeliveredInSeattle( );
持久化的3种方式:
开发人员实现SpringSecurity提供的UserDetialsService接口(告诉权限等),实例化到上下文,SpringSecurity就可以在上下文找到接口对象,返回UserDetails用户的详细信息
BEANPassWordEncoder也是需要开发人员实现SpringSecurity提供的接口->实例化到上下文,以便SpringSecurity进行加解密
绿色部分不需要开发人员操心,帮助进行用户名密码的认证工作(不需要自己实现Controller)会用到BEANPassWordEncoder和UserDetialsService实例
告诉SpringSecurity需要对哪些url进行控制
@EnableGlobalMethodSecurity 如果打开,可以实现方法级别的授权:PreAuthorize生效
@PreAuthorize("hasRole('ADMIN')")//方法级别的注解
public void deleteAllOrders() {
orderRepository.deleteAll();
}
.loginPage("/")
registry.addViewController("/login");
username
、password
,可配置容器就是一台轻量级虚拟机,里面有操作系统(文件管理等都有)
docker是一个软件,用于运行、管理容器
docker desktop是针对windows的GUI软件,会自动在本机创建VM(虚拟化出的linux)
在docker hub创建账号,存的是容器的镜像,可以下载很多软件。
容器技术支撑了微服务
-p:左边是主机端口,右边是容器端口
–rm:退出后自动删除容器
-d:后台运行,不用交互
-e:设置环境变量,操作系统中会有对应的环境变量
输入docker --help
volume:存储。容器消亡后,使数据可以继续保留在volumn里。
network:让虚拟机之间互联互通
container
image
此外,docker stop
的意思是停止运行的容器;但停止后可以重新启动(restart)
RUN:构建正在创建的映像,会创建image的新层
docker run 指令(-it/-p/-d等) 镜像名 参数(/bin/sh、bash等)
docker run -it test:1
和 docker run -it test:1 bash
,前者不会覆盖cmd,后者会覆盖cmdADD和COPY的区别:add会自动解压,copy只会拷贝(都可以将本地文件添加到容器中)
cmd和entrypoint的区别
CMD:容器启动以后,默认的执行的命令,如启动python程序
ENTRYPOINT:用entrypoint的中括号形式作为docker 容器启动以后的默认执行命令
区别1:ENTRYPOINT不会被docker run中的参数命令覆盖
区别2:如果在Dockerfile中CMD与ENTRYPOINT都存在,则CMD中的指
令将会被作为ENTRYPOINT中的参数,即这时候CMD里的指令会失去它的
作用,只是作为一个参数(可以理解为就是字符串)了。这时docker run
后的参数指令依然会覆盖CMD,但是也会失去他本身的作用,仅仅是作为
参数(字符串)提供给ENTRYPOINT中的命令
dockerignore:把不想要的文件排除在外
容器本来就轻量级,只运行单个应用
多个RUN合并:减少镜像的分层。可以把差不多变化频率的层放在一起。
和k8s同级,均可用于部署服务,如将多个服务一次性部署。
docker-compose ps:不是呈现docker系统中的所有容器,只是呈现当前目录下docker-compose所部署的容器(因为会运行当前目录下的docker-compose.yml文件进行部署)
docker-compose images同理,只是当前目录下的镜像
docker-compose logs -f [pod名字/服务的名字] 把里面的容器的日志打印出来
连续的-
或者一行
对象用{}
ingress:如何从集群外部访问端口?统一的入口——ingress,类似nginx的反向代理,根据域名作转发。
service :在k8s中不要直接访问具体pod,因为pod经常变换ip会变,所以用service。
deployment:pod版本管理的工具,用来区分不同版本的pod
单独创建pod的时候就不会有deployment出现,但是创建deployment的时候一定会创建pod,因为pod是一个基础的单位。
顾名思义“部署”:除了运行代码(即pod)之外,需要考虑更新策略,副本数量,回滚,重启等步骤
自动伸缩,设定伸缩个数的区间:
kubectl autoscale deployment spittr --min=10 --max=15 --cpu-percent=80
pod:调度的最小单位,一个或多个容器
背命名空间:默认情况下同一个POD的不同容器的哪些名称空间是打通的。这里先说一下结论,共享的是UTS、IPC、NET、USER。
pod可以在多个容器直接共享
是K8S调度的最小单元
port-forward
创建pod/service端口到本机端口的映射,实现对部署服务的访问ingress
,就可以通过域名来做路由。
curl
工具:基于http的访问通过label、service找到对应的pod
service有集群ip,也可以用来访问service(pod因为经常消亡,ip会变所以不能用)
共同点:通过服务名访问多个动态的服务实例。
不同点:
1-5的含义
在每个方法上加@ResponseBody或在类上加@ResponseController
可以加在方法上面,或者传参时参数里面
nacos:动态配置服务+服务发现及管理,可在docker/k8s部署
微服务的两大配置数据来源:Spring Cloud Config或nacos
在bootstrap中定义nacos的访问地址(server-addr)、后缀(file-extension)、服务名(application.name,可用来组合dataID,有固定的格式)
在代码中获取某一属性的值
还有nacos-config
如果用到了,还要加loadbalance和feign的依赖
openfeign会自动实现接口,但需要我们用@Autowired注入依赖:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QOwmG5op-1681124977865)(file://D:\新桌面\服务端开发\课堂笔记.assets\image-20230405231248135.png?lastModify=1680877021)]
不可访问:pod的名字不能,如licensingservice-69d757895c
SpringCloudAlibaba包括学过的nacos和sentinel,其他不用管
com.alibaba.cloud, spring-cloud-starter-alibaba-nacos-config
com.alibaba.cloud, spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud, spring-cloud-starter-loadbalancer
org.springframework.cloud, spring-cloud-starter-openfeign
后两种方法自动做负载均衡,因此一般不建议使用第一种(只在测试时使用),更常见的是第三种。我们定义的负载平衡策略(轮询、随机等)能影响到后两种方式。
临时实例的客户端主动上报机制, 临时实例每隔 5s 发送一个心跳包给 Nacos 服务器端
永久实例的服务端反向探测机制,永久实例支持 3 种探测协议,TCP、HTTP 和 MySQL,默认探测协议为 TCP,也就是通过不断 ping 的方式来判断实例是否健康。
licensingservice如何调用organizationservice?
错误:用nacos转发,licensingservice->nacos->organizationservice
正确:从nacos获取organizationservice的实例,如3个IP,客户端的loadbalancer以轮询或某种略侧从3个中选一个,然后直接通讯
Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
3种定义资源的方式
强调:外置文件只能定义规则,不能定义资源!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CMBWfIHG-1681124977867)(重点背诵.assets/image-20230408011850566.png)]
可在代码定义或者dashboard定义
QPS:每秒查询率。对查询服务器在规定时间内处理流量多少的衡量标准。
BlockException
DegradeException:熔断
FlowException:限流
Sentinel处理后会返回缺省值或者异常。
策略:
控制台不维护规则,通过端口号 8719 查询规则,如果服务故障则规则丢失。
在控制台定义规则后,会立刻应用到服务上。
@SpringBootApplication程序入口,进入
@profile(“dev”)名字可以随便起
@Profile("dev")//开发环境,一开始就实例化出来
@Profile("prod")//只在生产环境下才实例化出来,所以并不是同时实例化
@Conditional
@Conditional(MagicExistsCondition.class)//在某种情况下才实例化 参数是条件(这里是类实现)
@Qualifier :指出我们想要使用哪个 bean
@Valid注解会告诉spring进行校验(来自import javax.validation.Valid;)
@Data//lombok会帮忙生成get/set/equals/hashCode
public class Taco {
@NotNull
@Size(min=5, message="Name must be at least 5 characters long")
private String name;//taco的名字
@NotNull
@Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;//用户所指定的配料 Converter将id转成Ingredient
}
@SessionAttributes(“tacoOrder”)维持一段会话内tacoOrder的状态
@ModelAttribute:将请求参数绑定到 Model 对象。
@Repository:持久层的接口
@Controller:控制器层的接口
@Query:标记在继承了Repository的自定义接口方法上,就不需要遵循查询方法命名规则