一、Controller 方法返回的对象转换不成 JSON
demo 代码:
@RestController
@RequestMapping("/api/config")
public class ConfigController {
@RequestMapping("/")
public Response<List<Config>> config(@RequestParam("appName") String appName) {
List<Config> configs = getConfigsFromDB(appName);
return new Response<>(configs);
}
}
只加了 @RestController 或 @ResponseBody 注解,SpringMVC 在帮我们进行对象转 JSON 时会抛出下面的异常:
org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.selfservicerounds.utils.Response
所以要想把对象转换成 JSON 除了加 @RestController 或 @ResponseBody 注解,还必须进行以下的配置:
- 添加 maven 依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
- 添加代码
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
addDefaultHttpMessageConverters(converters);
}
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON);
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(mediaTypes);
return mappingJackson2HttpMessageConverter;
}
}
- 检查 Response 这个类有没有 get 方法。 Response 没有 get 方法,SpringMVC 帮我们把 Response 对象转 JSON 时也会报错。
SpringMVC 对象转 JSON 默认用的是 JackJson,如果对象都没有 get 方法,JackJson 进行对象转 JSON 时会直接抛异常。
- Gson 是通过反射遍历该类中的所有属性,并把其值序列化成json字符串;JackJson 和 fastJson 是通过 getter 方法获取属性,并把其值序列化成 json 字符串。具体原因,可以看这篇博客:fastJson、JackJson以及Gson序列化对象与get、set以及对象属性之间的关系。
二、前端请求的 JSON 参数转换不成 Controller 方法上的对象
背景
前端通过 json 数据的格式请求后端 /admin/updateDoctor 接口,后端 Controller 方法上的对象中的成员变量都为 null,并没有获取到前端 json 请求中的参数。
@RestController
@RequestMapping("/admin")
public class AdministratorController {
@Autowired
DoctorService doctorService;
/**
* 管理员更新医生信息
* @param doctors
* @return
*/
@RequestMapping("/updateDoctor")
public ResultInfo<String> updateDoctor(Doctors doctors){
ResultInfo<String> res = doctorService.updateDoctor(doctors);
return res;
}
}
解决方法
在 updateDoctor 方法的 Doctors 对象前加 @RequestBody ,该注解会把前端请求传来的 json 串的值填充到 Doctors 对象的成员变量中。
@RestController
@RequestMapping("/admin")
public class AdministratorController {
@Autowired
DoctorService doctorService;
/**
* 管理员更新医生信息
* @param doctors
* @return
*/
@RequestMapping("/updateDoctor")
public ResultInfo<String> updateDoctor(@RequestBody Doctors doctors){
ResultInfo<String> res = doctorService.updateDoctor(doctors);
return res;
}
}
三、properties 配置文件中文乱码
某 Spring 项目,application.properties 文件:
company.name=阿里巴巴
如果项目中通过 @Value("${company.name}")
引用了这个配置属性,会发现项目读取的字符串是一个乱码的字符串。
为什么呢?
因为 idea 编码时按照 UTF-8 编码的,@Value("${company.name}")
解码时是按照 ASCII 解码的,所以就乱码了。记住,乱码问题的本质就是编码和解码方式不一致导致的。
如何解决这个问题?
有四种解决方式:
- 自定义配置文件
- 通过@PropertySource(value=”classpath:my.properties”, encoding=”UTF-8”) 注解配置自定义文件,注意文件名不能是 springboot 默认的 application.properties 文件名称。
- 使用yml/yaml配置文件
- 将yml/yaml文件设置为UTF-8的编码格式,springboot读该文件即采用UTF-8编码。
- IDE/插件预编码
- 采用编译器或者插件将配置文件预编码,具体操作。
- 把中文配置编码成 ASCII 写入到配置文件中(推荐)
上述文字引用自该篇博客:https://eericzeng.github.io/2019/06/29/SpringBoot
总结
在配置 application.properties 时,都是开发比较重要的参数,尽量使用英文。如果业务上有的配置一定要中文配置,那建议把中文配置转成 ASCII 编码写入到配置文件中。
四、生成文件到 classpath 下
Web 类型的 maven 项目在编译打包后,resource 文件夹下的静态资源其实会打包到 classpath 下,如下图:
如果我们想在 classpath 的 static/img_code 路径下生成一张图片怎么办呢?
- 直接用下述代码即可实现:
// 1. 获取 classpath 的 static/img_code 路径 String destPath = this.getClass().getResource("/").getPath() + "static/img_code"; // 2. 生成文件 (生成文件的写法有很多,这里就不具体写了)