0%

说明

// Enum对象
@AllArgsConstructor
@Getter
public enum Type {
    SMS("sms"),
    APP("app"),
    UNKNOWN("unknown"),
    ;
    private String type;
}

// 实际的接口对象,里面有个属性是Enum
@Data
@Accessors(chain = true)
public class Noti {
    private Type type;
    private boolean sync;
}

springboot接口难免用到Enum类型,这个时候如何配置Enum类型序列化和反序列化呢?springboot默认使用的JSON序列化工具是jackson.

使用

// Enum对象
@AllArgsConstructor
@Getter
public enum Type {
    SMS("sms"),
    APP("app"),
    UNKNOWN("unknown"),
    ;
    private String type;

     @JsonCreator
    public static Type fromString(String value) {
        for (Type type : values()) {
            if (type.getType().equalsIgnoreCase(value)) {
                return type;
            }
        }
        return Type.UNKNOWN;
    }

    @JsonValue
    public String getTypeValue() {
        return type;
    }
}

// 实际的接口对象,里面有个属性是Enum
@Data
@Accessors(chain = true)
public class Noti {
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Type type;
    private boolean sync;
}

通过以上配置就可以实现, json中的字符串转化成Enum对象,以及Enum对象转化成json中的字符串.

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

添加websocket配置类

@Configuration
public class WebSocketConfig {
    /**
     * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

添加websocket Endpoint

@Slf4j
@Component 
@ServerEndpoint("/ws/{name}")
public class WebSocketTest {
    // @Component 虽然表示是springboot的单例,但是这个创建的单例并不会用到.
    // 实际新的websocket连接进来的时候, 会创建新的 WebSocketTest 实例,所以这里的name、session属性都是该连接私有的
    private String name;
    private Session session;

    // 可以创建一个构造器测试,是不是新的websocket连接进来会创建新的实例.
    // public WebSocketTest() {
    //     System.out.println("创建");
    // }

    // 可以创建一个静态属性保存所有的websocket连接
    // private static ConcurrentHashMap<String, WebSocketTest> webSocketSet = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "name") String name) {
        this.name = name;
        this.session = session;
        // name 是用来表示唯一客户端
        webSocketSet.put(name, this);
        System.out.println("OnOpen");
    }

    @OnClose
    public void OnClose() {
        System.out.println("OnClose");
    }

    @OnMessage
    public void OnMessage(String msg) throws IOException {
        System.out.println(msg);
        session.getBasicRemote().sendText("Hello " + name);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.info("发生错误");
        error.printStackTrace();
    }
}

测试

可以通过在线 websocket 客户端来测试你的 ws 服务:http://coolaf.com/tool/chattest.

创建密码

# 创建一个test用户,终端输入密码,然后保存到pwd文件中
htpasswd -c pwd test
# 可以cat pwd 看看密码
test:$apr1$XV.xFTZA$Gvuw/g8TAYYS6Nm5c7w5Q1
# 可以向这个文件继续添加用户test2,密码sss
htpasswd -b pwd test2 sss

nginx.conf

将上面生成的文件 pwd 放到 /etc/nginx/pwd目录下,并在 nginx.conf 指定位置.

server {
        listen    80 default_server;
        server_name _;
        location / {
            auth_basic "you need login";
            auth_basic_user_file /etc/nginx/pwd; 
            proxy_pass   http://xxxx:222;
            # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
            proxy_http_version 1.1;
            # Remove the Connection header if the client sends it,
            # it could be "close" to close a keepalive connection
            proxy_set_header Connection ""; 
      }
    }

注意proxy_http_version 1.1proxy_set_header Connection ""配置对于SSE这种需要保持长连接的接口很重要,一定要添加不然无数据返回. proxy_http_version指定版本,proxy_set_header设置Connection为空.

curl测试

# 第一种方式, -u 指定用户名密码
curl -u "test2:sss"   http://172.16.20.91:38750/sse/test

# 第二种,将用户名密码base64加密后添加到header
echo -n "test2:sss" | base64
curl -H "Authorization:Basic base64加密后的字符串" http://127.0.0.1:38750/test

IDEA快捷键

快捷键 说明
Shift + Ctrl + V 选择要粘贴的内容
Ctrl + Alt + L 重新格式化代码
Ctrl + F12 显示文件结构
Ctrl + ` 更改视图模式
Ctrl + G 转到行:列
Ctrl -/+ 收起和展开代码块
Alt + Shift + ,/. 缩小/放大字体
  • https://blog.jetbrains.com/zh-hans/idea/2022/11/intellij-idea-3/

VS Code快捷键

快捷键 说明
Shift + Ctrl + K 删除一行
Shift + Alt + ↑/↓ 向上/向下复制一行
Alt + ↑/↓ 向上/向下移动一行
Shift + Alt + f 代码格式化
Ctrl + Shift + n 新建一个窗口
Ctrl + ]/[ 行增加/减少缩进
Ctrl -/+ 字体放大/减小
Ctrl + b 显示/隐藏左侧目录栏
Ctrl + ~ 打开/关闭终端
Ctrl + Shift + ~ 打开新的终端
Ctrl + Shift + c 当前目录打开cmd窗口

说明

什么是准入 Webhook?

准入 Webhook 是一种用于接收准入请求并对其进行处理的 HTTP 回调机制。 可以定义两种类型的准入 Webhook, 即验证性质的准入 Webhook 和变更性质的准入 Webhook。 变更性质的准入 Webhook 会先被调用。它们可以修改发送到 API 服务器的对象以执行自定义的设置默认值操作。

Admission Webhook

包涵两种 CRD:mutatingwebhookconfigurationvalidatingwebhookconfiguration.

MutatingWebhookConfiguration 描述准入 Webhook 的配置,该 Webhook 可接受或拒绝对象请求,并且可能变更对象。

ValidatingWebhookConfiguration 描述准入 Webhook 的配置,该 Webhook 可在不更改对象的情况下接受或拒绝对象请求。

引用

说明

RestTemplate是Spring提供的用于访问Rest服务的客户端,可以通过ClientHttpRequestFactory创建。默认采用的是SimpleClientHttpRequestFactory,底层是HttpURLConnection(java.net包提供的方式),不具备连接池的功能,默认超时为-1。可以引入httpClient连接池

使用

  • 添加依赖
 <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version> <!-- 版本号可能会不同,根据实际情况选择 -->
</dependency>
  • 配置
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        ClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
        return new RestTemplate(factory);
    }

    private CloseableHttpClient httpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(50);
        connectionManager.setDefaultMaxPerRoute(50);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)
                .setConnectTimeout(10000)
                .setConnectionRequestTimeout(10000)
                .build();
        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }
}