slack-bot-0

Features

  • Init CM Request

  • Approve CM Request

  • Show CMs progress

  • Trigger CM Cut Build Flow

Basic Plan

4 weeks without further test and modifications

2 days for regular hotfix CMs in a week -> 3 days to work on the bot

3 days per feature -> only 12 hours per feature

WARNING: the bot is host outside the company network and cannot trigger jenkins jobs host inside, need workaround

1. get familiar w/ tutorial bot and general ideas, make it running

2 hours to implement Event Subscription api to talk with slack

1.1 cannot call slack/events api

只能用 22 端口,call 不通 3000

2. implement Init & Approve CM Request Part, with Authorization

3. implement Progress Tracking

4. implement CM Cut Build Flow with Jenkins Job

test-day-171

Today’s Task

  • CM Support
  • Slack bot

Additional Task

Thought

Slack Event Subscription

需要实现 events api 让 slack call 通

只能公司里面 call slack,但 slack call 不进来

workaround:

整一台私人的 AWS ,在上面实现,

然后公司的 slack bot 去通过这台 AWS 通信

需要非常强力的 Business Reason 提供给 Security 姐姐们

update:

失败了 = =

如果用私人的 AWS 的话联不通公司内网

Homework

  • Taco-cloud DB Integration
  • LeetCode Daily Question
  • Node.js w/ typescript

test-day-165

Today’s Task

  • Adjust CTS release pipeline default version
  • Docker image scripts
  • Prototype of Temp CM Notification Tool

Additional Task

  • CM Support - Resolve merge conflict
  • CM Support - Citadel image for PROD
  • Test Nexus & CP image for Matt
  • Fix Bugs from resolving merge conflict

Thought

= = 早上修 Merge Conflict 的时候没有仔细看 xml 配置

漏掉了关闭标签的部分

修的时候仔细看下,或者起不来的时候看下更深一些的报错,其实都可以发现的来着……

感觉好浪费时间啊啊啊啊

不能信任 Merge Conflict 箭头包出来的部分修完在语法上一定就是没有问题的

必须自己再检查一遍完整的文件

java-spring-4

Spring Web App

  • 映射请求到 Spring Controller

  • 透明绑定表单参数

  • 校验表单提交

Model View Controller

Spring MVC 起步

调度 Servlet,Handler Mapping, Controller, View Resolver

Spring 会将请求在上述几个之间移动

Request -> DispatcherServlet -> Handler Mapping -> Controller -> DispatcherServlet -> View Resolver -> View -> Response

1. Requset -> DispatcherServlet

Spring MVC 所有请求都会通过 Front Controller Servlet, 也就是 DispatcherServlet

DispathcerServlet 会把请求委托给其他组件处理

2. DispatcherServlet -> Handler Mapping -> Controller

DispatcherServlet 会去查询 Hander Mapping 决定将请求发到哪个具体的 Controller

通过 URL 决定

业务逻辑一般交给 Controller 去处理

Controller 会去处理 Request Payload

3. Controller -> DispatcherServlet

Controller 处理完 request 之后会有产生额外的信息,返回给用户显示在浏览器上

这些信息便是 Model

View 用来把原始信息处理成用户友好的格式, HTML

Controller 会把 Model 打包,连同 Request 和 View 名字一起发给 DispatcherServlet

4. DispatcherServlet -> View Resolver -> View

DispatcherServlet 收到的只是 View 的名字,所以可以用 ViewResolver 去通过名字找到真正对应的 View 实现

5. View -> Response

DS 把 Model 数据交给 View 实现完之后,请求就结束了,

View 会用 Model 数据来渲染输出,把 Response 交到 Client

java-spring-boot-3

validation error

import javax.validation.* 会失效,原因是 Spring Boot 在 2.3.0 以后就不再默认包含在 web-starter 里面了

在 pom.xml 里加上了相关的依赖 = =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>

明天看下第四版里面 spel 表达式的部分

稍微调整了下 IDEA 的 Run, Build 和 Terminal, 设置成窗口扔在另一块屏幕上,看起来舒服太多太多了

Alt + 4 RUN Window

Alt + F12 Terminal

Shift + F10 Run xxx

WebMvcConfigurer no interface expected here

java: method does not override or implement a method from a supertype

一不小心把 implements 写成 extends 了……

java-spring-3

4. 面向切面的 Spring

  • 面向切面编程的基本原理

  • 通过 pagp创建切面

  • 使用 @AspectJ 创建注解

  • 为 @AspectJ 切面注入依赖

横切关注点 Cross cutting Concern: 散布于应用中多处的功能

AOP想要解决的问题把这些横切关注点和业务逻辑相分离

切面实现了跨多个应用对象逻辑的模块化

4.1 AOP 是啥

通知 Advice

切面的 What 和 When

定义切面是什么,何时使用

可以应用五种类型

  • 前置通知 before

目标方法调用前通知

  • 后置通知 after

目标方法完成之后,输出无所谓

  • 返回通知 After-returning

目标方法成功执行之后,成功执行

  • 异常通知 After-throwing

目标方法抛出异常之后

  • 环绕通知 Around

通知包裹被通知方法,包起来,调用之前和调用之后执行自定义行为

切点 Pointcut

切面的 Where

连接点 Joinpoint

应用执行过程中插进切面的点

切面 Aspect

通知 + 切点

引入 Introduction

朝现有的类添加新方法或者属性

织入 Weaving

把切面应用到目标对象,创建新的代理对象

AOP 支持

Spring 提供了四种类型的 AOP 支持

  • 基于代理的经典 Spring AOP

  • 纯 POJO 切面

  • @AspectJ 注解驱动的切面

  • 注入式 AspectJ 切面

Spring 通知是 java 写的

定义通知应用的切点通常可以用注解,或者在 Spring 配置文件里用 xml 写

通过在代理类中包裹切面, Spring 在运行期把切面织入到 Spring 管理的 Bean 中

Spring 只支持方法级别的连接点

这些概念是一个字都没看懂 = =

看看具体的示例代码可能心里就会有数了

test-day-164

Today’s Task

  • Docker remove local image script
  • Adjust CTS release pipeline default version

Additional Task

  • CP image & deploy
  • nucleus, nexus, shadowbroker create branch for 8574
  • tag yesterday afternoon’s cm regression & wiki page update

Thought

昨天第三章看得属实云里雾里

今天再仔细看下它想说些什么吧

上周五清了 50 GB 的历史 image,因为需要确认安全,是手动 docker rmi -f 的……

这回花10分钟撸了个 script 去通过关键词找 container id,然后直接对着找出来的列表循环删 image

毋庸置疑,快多了

test-day-163

Today’s Task

  • Docker remove local image script
  • Adjust CTS release pipeline default version

Additional Task

  • Recut nucleus
  • new INT CM cut build, deploy & regression
  • cp, v5, build & deploy from test branch

Thought

测的时候发现之前那十几个 repo 的 script 全都改炸了…

每个问题都还不一样…

有些是路径配的有问题,有些是尝试去删了一个莫名其妙的 Docker image id

CP 有时候容易跑不起来或者 build 不过

这个时候需要去 nova utility 上 mvn clean install 一趟 dodo

java-spring-2

3. 高级装配

  • Spring profile

  • 条件化 Bean 声明式

  • 自动装配

  • Bean 作用域

  • Spring 表达式语言

3.1 Spring profile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class DataSourceConfig {

@Bean(destroyMethod="shutdown")
@Profile("dev")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDataabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}

@Bean
@Profile("prod")
public DataSource jndiDataSource() {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) jndiObjectFactoryBean.getObject();
}
}

不指定 profile 的 bean始终都会被创建

激活 profile 依赖 spring.profiles.activespring.profiles.default 属性

有 active 的就用 active,没有的话用 default,两个都没有的话就没有激活的 profile

设置方式:

DispatherServlet 的初始化参数

Web 应用的上下文参数

JNDI 条目

环境变量

JVM 系统属性

int 测试类上用 @ActiveProfiles 注解

3.2 条件配置 Bean

1
2
3
4
5
@Bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean() {
return new MagicBean();
}
1
2
3
4
5
6
public class MagicExistsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
return env.containsProperty("magic");
}
}

3.3 自动装配的歧义性

如果同时存在多个 Bean 匹配结果的话自动装配失效, NoUniqueBeanDefinitionException

1
2
3
4
@Autowired
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
1
2
3
4
5
6
7
8
9
@Component
public class Cake implements Dessert { ... }

@Component
public class Cookies implements Dessert { ... }

@Component
public class IceCream implements Dessert { ... }

解决方式:primary bean, qualifier bean

1
2
3
@Component
@Primary
public class IceCream implements Dessert { ... }

primary 只能同时存在一个

1
2
3
4
5
@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert
}

限定符必须和要注入的 bean 名称紧耦合

所有使用 @Component 声明的类都会创建为 Bean,并且 Bean ID 首字母变为小写的类名

@Qualifier 也可以和 @Component 组合使用,自定义限定符

也可以创建自定义注解

1
2
3
4
5

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold { }

3.4 Bean 作用域

默认情况下 bean 是作为单例创建的,不管注入多少次都是同一个实例

如果类里面会保持某些状态,单例重用会比较麻烦,容易污染对象

作用域:

  • 单例 Singleton

  • 原型 Prototype 每次注入或者通过 AC 获取的时候都会创建一个新的示例

  • 会话 Session

  • 请求 Request

1
2
3
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad { ... }

3.5 运行时值注入

属性占位符 Property Placeholder

SpEL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@PropertySource("classpath:/com/soundsystem/app.properties")
public class ExpressiveConfig {

@Autowired
Environment env;

@Bean
public BlankDisc disc() {
return new BlankDisc(
env.getProperty("disc.title"),
env.getProperty("disc.artist")
)
}
}

getProperty 还可以用来在所需属性不存在的时候指定默认值

如果需要属性一定存在的话可以用 getRequiredProperty

1
2
3
String getProperty(String key, String defaultValue)

T getProperty(String key, Class<T> type, T defaultValue)

java-spring-boot-2

解决了昨晚的 design 页无法渲染列表项,原因是忘了在它 Controller 里把列表项的内容塞进 model 里去

吐槽

Thymeleaf 平时真的用得到吗……

前后端的东西都混杂在一起,感觉像是在考古

可以的话我喜欢把前端的部分拆开来用更现代一些的框架单独写…

另外后端支持 Live Reload, 但是改了 thymeleaf 的 template 我不确定这个部分算是能不能 Reload ……

反正赶紧把这个部分快速过掉,然后看一些后端那边的东西吧

github 上扔了一大堆浅尝辄止的 Demo, 但没有一个方向是专精的

这些其实也是以前遗憾执念的一部分

这几年里这些遗憾积累得实在太多太多了,能补掉的就尽量一个个补过来吧

写完这个要去大吃一顿 Taco Bell