Spring
异常处理
异常类
/**
* 不能用 @Data 注解,因为它没有继承自 Object
*/
public class CustomException extends RuntimeException {
private Long code;
private String msg;
public CustomException(Long code, String msg){
this.code = code;
this.msg = msg;
}
public Long getCode() {
return code;
}
public void setCode(Long code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
处理器
import com.penruins.irds.entity.exception.CustomException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 自定义异常APIException
*/
@ExceptionHandler(CustomException.class)
// @ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String,Object> customExceptionHandler(CustomException e) {
Map<String, Object> map = new HashMap<>();
map.put("code", e.getCode());
map.put("msg", e.getMsg());
return map;
}
}
测试 Controller
@GetMapping("/testException")
public String testException() {
if(1 == 1) {
throw new CustomException(100L,"error!!!!");
}
return "hello";
}
- reference
AOP
aspect
- basic knowledge
- 使用@Aspect注解将一个java类定义为切面类
- 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等。
- 根据需要在切入点不同位置的切入内容
- 使用@Before在切入点开始处切入内容
- 使用@After在切入点结尾处切入内容
- 使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
- 使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
- 使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Aspect
@Component
@Slf4j
public class WebLogAspect {
@Pointcut("execution(public * com.penruins.irds.controller..*.*(..))")
public void webLog(){}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
log.info("URL : " + request.getRequestURL().toString());
log.info("HTTP_METHOD : " + request.getMethod());
log.info("IP : " + request.getRemoteAddr());
log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
log.info("RESPONSE : " + ret);
}
}
- reference
定时任务
step1 启动类添加注解 @EnableScheduling
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class IrdsApplication {
public static void main(String[] args) {
SpringApplication.run(IrdsApplication.class, args);
}
}
step2 创建定时任务
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class WhiteListSchedule {
@Scheduled(cron = "*/5 * * * * ?")
public void visitorPicToWhiteList() {
log.info("you don't give up then there's no limitation.");
}
}
- reference
RestTemplate
超文本传输安全协议
Hypertext Transfer Protocol Secure
HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包
HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性
/**
* HttpEntity 的结构
* HttpEntity 是对HTTP请求的封装,包含两部分, header 和 body
* header用于设置请求头,而body则用于设置请求体
**/
HttpEntity<String> requestEntity = new HttpEntity<String>(value, headers);
/**
* Form 解析可以直接从 request 对象中获取请求参数,这样对象转换与处理相对容易,但在
* 大片JSON数据需要提交时,可能会出现大量的数据拆分与处理工作
*
* 而Payload的优势是一次可以提交大量JSON字符串,但无法从Request中获取参数,也会受限于
* JSON解析的深度
*/
HttpHeaders headers = new HttpHeaders();
// form 表单提交
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// payload 提交
headers.setContentType(MediaType.APPLICATION_JSON);
/**
* 用 exchange 方法提交
*
* exchange 可以执行所有 http的方法
*/
Reference
- 易筋SpringBoot 2.1 | 第三篇:RestTemplate请求HTTP(1)
- 易筋SpringBoot 2.1 | 第四篇:RestTemplate方法详解(2)
- 易筋SpringBoot 2.1 | 第五篇:RestTemplate请求https(3)
- HttpClient、OKhttp、RestTemplate对比
- 使用RestTemplate访问https实现SSL请求
- java实用型-高并发下RestTemplate的正确使用
- RestTemplate 深度解析
- RestTemplate总结
- problems
spring data
Springboot JPA 是依赖与 Hibernate
javax.persistence.javax.persistence-api 定义了一些接口规范,但没有实现
Reference
feign
-
Feign 是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解。
-
Feign 可帮助我们感悟便捷,优雅的调用 HTTP API
-
在 SpringCloud中,使用 Feign 非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了
-
请求压缩
- Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗
-
通过
@EnableFeignClients引入了FeignClientsRegister客户端注册类 -
Feign 原理
- 启动时,程序会进行包扫描,扫描所有包下所有
@FeignClient注解的类,并将这些类注入到 spring的IOC容器中。当定义的 Feign 中的接口被调用时,通过JDK的动态代理来生成 RequestTemplate - RequestTemplate 生成 Request,然后将 Request 交给 client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp,apache的HTTPClient等
- 最后 client 封装成 LoadBalanceClient, 结合ribbon负载均衡地发起调用
- 启动时,程序会进行包扫描,扫描所有包下所有
-
Feign 浅谈 ppt 东北研发中心
okHttp
- OkHttp 是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求
- 当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。
绕过 http ssl
import okhttp3.OkHttpClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
/**
* Author: areful
* Date: 2019/2/15
*/
public class OKHttpClientBuilder {
public static OkHttpClient.Builder buildOKHttpClient() {
try {
TrustManager[] trustAllCerts = buildTrustManagers();
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier((hostname, session) -> true);
return builder;
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
return new OkHttpClient.Builder();
}
}
private static TrustManager[] buildTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
}
}
@GetMapping("/testApis")
public String testApi() {
String url = "https://randomuser.me/api/";
OkHttpClient client = OKHttpClientBuilder.buildOKHttpClient().build();
Request request = new Request.Builder()
.url(url)
.get()
.build();
Response response = null;
try {
response = client.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
- reference
mq
JmsTempalte
- reference
springboot两个mq
热更新
RequestContextHolder
- reference
mess
- reference
浙公网安备 33010602011771号