文章目录
@EuqalsAndHashCode
lombok插件的注解、
@EqualsAndHashCode(callSuper = false)
此注解会生成equals(Object other) 和 hashCode()方法。
1.它默认使用非静态,非瞬态(transient)的属性。
2.默认不使用父类的属性,即callSuper默认为false
3.指定为true则在1的基础上调用父类的方法
@Valid和@Validated
javax提供了@Valid(标准JSR-303规范)
@Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Valid不提供分组功能
都可以作用在类、字段、参数上进行检验
当作用在参数上时:通过对标注有@Valid或者@Validated的JavaBean进行校验,并将校验结果封装在BindResult中。注意这个BindResult必须是紧接着的下一个参数。
<!--由于SpringBoot 2.3版本默认移除了校验功能,如果想要开启的话需要添加如下依赖。-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
作用在参数上的示例
@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Min(value = 100,message = "id必须大于100")
private long id;
private String name;
}
@GetMapping("/check")
public ResponseEntity<String> checkUser(@Valid User user, BindingResult result) {
if (result.hasErrors()) {
List<ObjectError> allErrors = result.getAllErrors();
allErrors.stream().forEach(System.out::println);
return ResponseEntity.badRequest().body("id必须大于100");
}
return ResponseEntity.ok("hello");
}
常用校验注解 属于javax.validation.constraints
@Null 被注释的元素必须是null
@NotNull 被注释的元素不能为null
@AssertFalse 被注释的元素必须为false
@AssertTrue 被注释的元素必须是true
(字符串/数组/集合)校验:
@Pattern(regexp=“reg”) 被注释的元素必须符合给定的正则表达式
@Size(max, min) 被注释的元素的长度必须在范围内
@NotEmpty 被注释的元素不为空或者null
@NotBlank 被注释的元素不为null或者trim()后不为空
数值校验:
@Max(value) 被注释的元素必须是一个数字,并且小于或者等于指定的int值
@Min(value) 被注释的元素必须是一个数字,并且大于或等于指定的int值
@DecimalMax(value) 被注释的元素必须是一个数字,并且小于或者等于指定的值
@DecimalMin(value) 被注释的元素必须是一个数字,并且大于或等于指定的值
@Digits(integer, fraction) 被注释的元素必须是一个数字, 精整数度小于等于integer;小数部分精度小于fraction
@Range(min=long1, max=long2) 被注释的元素必须是一个数字,其值必须>=long1,并且<=long2
日期校验:Date/Calendar
@Post 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个未来的日期
当校验失败时,SpringBoot默认会抛出MethodArgumentNotValidException或BindException异常,我们只要全局处理该异常依然可以得到校验失败信息。
@ResponseEntity
ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。
@GetMapping("/hello")
ResponseEntity<String> hello() {
return new ResponseEntity<>("Hello World!", HttpStatus.OK);
// return ResponseEntity.ok("Hello World!");
}
@GetMapping("/age")
ResponseEntity<String> age(
@RequestParam("yearOfBirth") int yearOfBirth) {
if (isInFuture(yearOfBirth)) {
return new ResponseEntity<>(
"Year of birth cannot be in the future",
HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(
"Your age is " + calculateAge(yearOfBirth),
HttpStatus.OK);
/**
if (isInFuture(yearOfBirth)) {
return ResponseEntity.badRequest()
.body("Year of birth cannot be in the future");
}
return ResponseEntity.status(HttpStatus.OK)
.body("Your age is " + calculateAge(yearOfBirth));
**/
}
@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {
HttpHeaders headers = new HttpHeaders();
headers.add("Custom-Header", "foo");
return new ResponseEntity<>(
"Custom header set", headers, HttpStatus.OK);
/**
return ResponseEntity.ok()
.header("Custom-Header", "foo")
.body("Custom header set");
**/
}
ResponseStatus
@ResponseStatus的作用是改变HTTP响应的状态码,使用范围:RequestMapping、ExceptionHandler、自定义异常类。
@GetMapping("/check")
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "test")
public ResponseEntity<String> check() {...
@Order
注解可以作用在类、方法、字段声明(包括枚举常量);
@Order 用来控制优先级的,越小优先级越高。默认值为Integer.MAX_VALUE,即最低优先级。
需要注意的是@Order不能控制Bean加载顺序,但是对依赖注入的顺序有影响。
You can declare the @Order annotation at the target class level and on @Bean methods, potentially for individual bean definitions (in case of multiple definitions that use the same bean class). @Order values may influence priorities at injection points, but be aware that they do not influence singleton startup order, which is an orthogonal concern determined by dependency relationships and @DependsOn declarations.
常见的用法还有当定义了多个@ControllerAdivce或者多个@Aspect时,使用@Order指定异常处理或者切面的优先级
RSA算法
RSA是一种非对称加密算法
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密。
如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全
URI和URL
URI = Uniform Resource Identifier 统一资源标识符
URL = Uniform Resource Locator 统一资源定位符
URN = Uniform Resource Name 统一资源名称
URI 在于I(Identifier)是统一资源标示符,可以唯一标识一个资源。
URL在于Locater,一般来说(URL)统一资源定位符,可以提供找到该资源的路径,
比如https://www.zhihu.com/question/21950864
但URL又是URI,因为它可以标识一个资源,所以URL又是URI的子集。
总的来说,locators are also identifiers, so every URL is also a URI, but there are URIs which are not URLs.
HTTP请求报文和响应报文
请求报文
HTTP请求报文由3部分组成(请求行+请求头+请求体)。请求头和请求体之间存在一行空行
响应报文
HTTP响应报文主要由状态行、响应头部、响应正文3部分组成
@ModelAttribute
作用范围:方法和参数
示例
被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用。
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountManager.findAccount(number);
}
@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld";
}
addAccount方法在helloWorld方法之前先被调用,在这种情况,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回Account类型,那么这个model属性的名称是account,属性值为方法返回值。在它执行后helloWorld被调用。
也可以通过 @ModelAttribute(“attributeName”)指定model属性的名称
@ModelAttribute("user")
public User addAccount() {
return new User("a","123");
}
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute("user") User user) {
return "helloWorld";
}
作用于参数时,可以获取model中的属性值。
此时如果方法体没有标注@SessionAttributes(“user”),那么scope为request,如果标注了,那么scope为session
字
一个字节(byte)等于8位(bit)
16位系统中,一个字等于16位,即2个字节
32位系统中,一个字等于32位,即4个字节
64位系统中,一个字等于64位,即8个字节
字是计算机一次处理数据的最大单位。多数情况下,这有几个含义:
CPU的寄存器的长度是一个字;
CPU一个指令最多从内存中读取的数据量就是一个字;
最大的寻址空间,是2^字长(如果一个字是64位,那么最大的寻址空间就是2的64次方)
基本类型 大小 取值范围 装箱基本类型
int 4个字节 -2^31 ~ 2^31-1 Integer
char 2个字节 Character
byte 1个字节 -2^7 ~ 2^7-1 Byte
short 2个字节 -2^15 ~ 2^15-1 Short
long 8个字节 -2^63 ~ 2^63-1 Long
float 4个字节 Float
double 8个字节 Double
boolean 4个字节 true ~ false Boolean
MD5
MD5即Message-Digest Algorithm 5(信息-摘要算法5),是一种不可逆的加密规则算法,比如将敏感信息的密码MD5加密后存储到数据库。用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
MD5算法具有这些特点:
压缩性,任意长度的数据,算出的MD5值长度都是固定的(通常32位的16进制字符串);容易计算,从原数据计算出MD5值很容易;
抗修改性,对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别;
强抗碰撞,已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
MD5加密的特点主要有以下几点:
1、针对不同长度待加密的数据、字符串等等,其都可以返回一个固定长度的MD5加密字符串。(通常32位的16进制字符串,即128bits);
2、其加密过程几乎不可逆,除非维护一个庞大的Key-Value数据库来进行碰撞破解,否则几乎无法解开。
3、运算简便,且可实现方式多样,通过一定的处理方式也可以避免碰撞算法的破解。
4、对于一个固定的字符串。数字等等,MD5加密后的字符串是固定的,
public class Main {
public static void main(String[] args) throws Exception {
// 创建一个MessageDigest实例:
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("Hello".getBytes("UTF-8"))
byte[] result = md.digest();
//把它转换为十六进制的字符串。
System.out.println(new BigInteger(1, result).toString(16));
}
}
//32位16进制的字符串
//sout:f5a7924e621e84c9280a9a27e1bcb7f6
@Import
只能作用在类上
@Import注解可以把指定的类加入spring的IOC容器中,注入的Bean id为全类名。
支持的类
1.带有@Configuration的配置类(4.2 版本之前只可以导入配置类,4.2版本之后可以导入普通类
2.ImportSelector 接口的实现类 [返回需要导入的组件的全类名数组;]
3.ImportBeanDefinitionRegistrar 接口的实现类 [实现手动注册bean到容器中]
可以用于第三方依赖包中Bean的加载
spring.profiles.active
spring boot允许你通过命名约定按照一定的格式(application-{profile}.properties)来定义多个配置文件(bootstarp同理)。然后通过spring.profiles.active来具体激活一个或者多个配置文件,如果没有没有指定任何profile的配置文件的话,spring boot默认会启动application-default.properties。
@ConfigurationProperties
spring-boot 提供该注解将配置文件的值映射到类上的字段。可以通过prefix属性指定配置文件中的属性前缀
示例
secure:
ignore:
urls: #配置白名单路径
- "/swagger-resources/**"
- "/swagger/**"
- "/**/v2/api-docs"
/**
* 网关白名单配置
* Created by macro on 2020/6/17.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Component
@ConfigurationProperties(prefix="secure.ignore")
public class IgnoreUrlsConfig {
private List<String> urls;
}
cookie、session、token
https://blog.csdn.net/javaQQ561487941/article/details/89554225
HTTP协议本身是无状态的,客户只需要简单的向服务器来发送请求下载某些文件,客户端向服务器端发送的每次请求都是独立的。对于当前的web应用,HTTP的“无状态”,导致许多应用都不得不花费大量的精力来记录用户的操作步骤。
cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。
当用户第一次通过浏览器使用用户名和密码访问服务器时,服务器会验证用户数据,验证成功后在服务器端写入session数据,向客户端浏览器返回sessionid(jsessionid),浏览器可以将sessionid保存在cookie中,当用户再次访问服务器时,会携带sessionid,服务器会拿着sessionid获取session数据,从而实现状态保持。
对于token:
①认证成功后,会对当前用户数据进行加密,生成一个加密字符串token,返还给客户端
(服务器端可以保存在缓存或者数据库,如果使用的是jwt的话就无需保存,因为jwt具有自解释性)
再次访问时只需携带token,服务器校验浏览器传来的token
CSRF
CSRF全称为跨站请求伪造(Cross-site request forgery),是一种网络攻击方式,也被称为 one-click attack 或者 session riding。
简单来说就是: 你访问了信任网站 A,然后 A 会用保存你的个人信息并返回给你的浏览器一个cookie,然后呢,在 cookie 的过期时间之内,你去访问了恶意网站 B,它给你返回一些恶意请求代码,要求你去访问网站 A,而你的浏览器在收到这个恶意请求之后,在你不知情的情况下,会带上保存在本地浏览器的 cookie 信息去访问网站 A,然后网站 A 误以为是用户本身的操作,导致来自恶意网站 B 的请求会被执行。
解决方案
使用验证码
关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。
使用token
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。
参考
https://blog.csdn.net/neweastsun/article/details/81142870
https://www.zhihu.com/question/21950864
https://blog.csdn.net/javaQQ561487941/article/details/89554225