Web开发常见问题汇总-爱代码爱编程
Spring注解之@Scope
@Scope
注解是Spring IOC
容器中的一个作用域,在Spring IOC
容器中具有以下几种作用域:
基本作用域singleton(单例)、prototype(多例),Web作用域(reqeust、session、globalsession),自定义作用域
- singleton(单例模式):全局有且仅有一个实例
- prototype(原型模式):每次获取bean的时候会有一个新的实例
- request:针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
- session:针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
- globalsession:类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义
Cause: java.lang.IllegalArgumentException: argument type mismatch
错误信息:
nested exception is org.apache.ibatis.reflection.ReflectionException: Error instantiating class * with invalid types () or values (). Cause: java.lang.IllegalArgumentException: argument type mismatch
错误原因:
- @Data 和 @Builder 导致无参构造丢失
- 单独使用@Data注解,是会生成无参数构造方法。
- 单独使用@Builder注解,发现生成了全属性的构造方法。
@Data和@Builder同时使用:没有了默认的构造方法。如果手动添加无参数构造方法或者用@NoArgsConstructor注解都会报错!
解决方法:使用@Builder
注解,最简单的方法就是直接写上以下4个注解:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
- @Builder 注解导致默认值无效
解决方法:在默认值上,加上@Builder.Default
注解
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field
错误信息:
Exception in thread “main” com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “age” (class com.daling.bpmn.test.User), not marked as ignorable (3 known properties: “id”, “name”, “flag”])
错误原因:反序列化时,遇到未知属性
解决方案:
-
添加注解:@JsonIgnoreProperties(ignoreUnknown = true)
-
配置策略
ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
雪花算法与精度丢失问题
问题描述:JavaScript
无法处理Java
的长整型Long
导致精度丢失,具体表现为主键最后两位永远为0
解决思路:Long
转为String
返回
解决方案:
-
FastJson 处理方式
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fjc = new FastJsonConfig(); // 配置序列化策略 fjc.setSerializerFeatures(SerializerFeature.BrowserCompatible); fastJsonConverter.setFastJsonConfig(fjc); converters.add(fastJsonConverter); }
-
JackJson 处理方式
-
方式一
// 注解处理,这里可以配置公共 baseEntity 处理 @JsonSerialize(using=ToStringSerializer.class) public long getId() { return id; }
-
方式二
// 全局配置序列化返回 JSON 处理 final ObjectMapper objectMapper = new ObjectMapper(); SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); objectMapper.registerModule(simpleModule);
Cannot determine value type from string ‘’
错误原因:当使用了@Builder
注解之后会默认把无参构造方法忽略掉,创建一个全参的构造方法
解决方法:使用@Builder
注解,最简单的方法就是直接写上以下4个注解:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
无法反序列化LocalDateTime
解决方法:在实体类字段中添加注解
// 需要哪个用哪个
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@Mapper和@Repository区
@Repository需要在Spring中配置扫描地址,然后生成Dao层的Bean才能被注入到Service层中。
@Mapper不需要配置扫描地址,通过xml里面的namespace里面的接口地址,生成了Bean后注入到Service层中。
@Validated和@Valid区别
- 基本概念
Spring Validation 验证框架对参数的验证机制提供了@Validated(Spring’s JSR-303规范,是标准JSR-303的一个变种)。
javax提供了@Valid(标准JSR-303规范),配合BindingResult
可以直接提供参数验证结果。
- 主要区别
@Validated | @Valid | |
---|---|---|
分组 | 提供分组功能,可在入参验证时,根据不同的分组采用不同的验证机制。 | 无分组功能 |
可注解位置 | 可以用在类型、方法和方法参数上。但是不能用在成员属性上 | 可以用在方法、构造函数、方法参数和成员属性上(两者是否能用于成员属性上直接影响能否提供嵌套验证的功能) |
嵌套验证 | 用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性上。也无法提供框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。 | 用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。 |
StringRedisTemplate和RedisTemplate区别
两者的关系是StringRedisTemplate继承RedisTemplate。
两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
两者之间的区别主要在于他们使用的序列化类:
StringRedisTemplate默认采用的是String序列化策略(StringRedisSerializer
)。
RedisTemplate默认采用的是JDK序列化策略(JdkSerializationRedisSerializer
),存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
使用时注意事项:
当你的Redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么使用StringRedisTemplate即可。
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
RedisTemplate使用时常见问题:
RedisTemplate中存取数据都是字节数组。当Redis中存入的数据是可读形式而非字节数组时,使用RedisTemplate取值的时候会无法获取导出数据,获得的值为null
。可以使用StringRedisTemplate
试试。
classpath和classpath*区别
- classpath:默认只会在你项目的class路径中查找文件
- classpath*:默认不仅包含class路径,还包括jar文件中(class路径)进行查找
使用classpath*:Spring需要遍历所有的classpath,所以加载速度是很慢的;故在设计中,应该尽可能划分好资源文件所在的路径,尽量避免使用classpath*。
401与403的区别
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
401 | Unauthorized | 该HTTP状态码表示认证错误,它是为了认证设计的,而不是为了授权设计的。收到401响应,表示请求没有被认证—压根没有认证 或者认证不正确 —但是请重新认证和重试。(一般在响应头部包含一个WWW-Authenticate来描述如何认证)。通常由web服务器返回,而不是web应用。从性质上来说是临时的东西 。(服务器要求客户端重试) |
403 | Forbidden | 该HTTP状态码是关于授权方面的。从性质上来说是永久的东西 ,和应用的业务逻辑相关联。它比401更具体,更实际。收到403响应表示服务器完成认证过程,但是客户端请求没有权限去访问要求的资源 。 |
- 401:Unauthorized响应,应该用来表示缺失或错误的认证。
- 403:Forbidden响应,应该在这之后用,当用户被认证后,但用户没有被授权在特定资源上执行操作。