Java SonarLint:返回空集合而不是null
我正在对一个返回对象列表的方法进行ajax调用,如果在try-catch块中获取数据时发生了什么,我会有一个响应。setStatus400将在前端显示错误,在那里我返回null,在那里我会收到SonarLint通知。现在,如果我将其更改为空集合,则会出现以下错误: 已为此响应调用getWriter 我认为以上是因为我返回的是空集合和http响应状态400。如果我将其保留为空,则所有操作都可以正常工作,只需SonarLint通知即可Java SonarLint:返回空集合而不是null,java,spring-boot,sonarlint,Java,Spring Boot,Sonarlint,我正在对一个返回对象列表的方法进行ajax调用,如果在try-catch块中获取数据时发生了什么,我会有一个响应。setStatus400将在前端显示错误,在那里我返回null,在那里我会收到SonarLint通知。现在,如果我将其更改为空集合,则会出现以下错误: 已为此响应调用getWriter 我认为以上是因为我返回的是空集合和http响应状态400。如果我将其保留为空,则所有操作都可以正常工作,只需SonarLint通知即可 @GetMapping("/runquery") @Respon
@GetMapping("/runquery")
@ResponseBody
public List<Map<String, Object>> runQuery(@RequestParam(name = "queryId") String queryId, @RequestParam(name = "formData") String formData, HttpServletResponse response) throws IOException {
(...)
try {
queryResult = namedParameterJdbcTemplateHive.queryForList(query, paramSource);
for (Map<String, Object> map : queryResult) {
Map<String, Object> newMap = new HashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (key.contains(".")) {
key = key.replace(".", "_");
newMap.put(key, value);
} else {
newMap.put(key, value);
}
}
queryResultFinal.add(newMap);
}
} catch (Exception e) {
response.setStatus(400);
response.getWriter().write(e.getMessage());
return null; <-- SonarLint notification
}
return queryResultFinal;
}
您知道如何修复此通知吗?我建议不要用此方法捕获异常,而是抛出异常,并使用控制器中的来处理它。在这种情况下,您将永远不会从该方法返回null,Sonar将没有什么可抱怨的。这也意味着您正在按设计使用的方式使用Spring 例如,如下所示:
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handleException(Exception e) {
log.error("Exception during request", e);
}
或直接等同于您当前的处理方式:
@ExceptionHandler
public ResponseEntity<?> handleException(Exception e) {
return ResponseEntity.badRequest().body(e.getMessage()).build();
}
切换到异常处理程序后,您可以从常规方法中删除HttpServletResponse参数。我建议您创建一个通用报告来包装所有响应,这对于前端来说也是非常好的,因为您面对的是一个固定的模板 因此,通过这个解决方案,您可以包装您想要的任何对象并将其发送到响应 我对场景进行了如下编码: 1-创建GenericResponse类 3-创建异常时使用的异常转换器服务 4-使用GenericResponse更改场景 您需要做的只是: 创建前面提到的类复制我在1、2和3中编写的代码 将响应表单列表更改为GenericResponse 将您的返回类型包装到GenericResponse中 我改变了你的代码如下只改变3行
@RestController
public class TestController {
@Autowired
private ExceptionConverterService exceptionConverter;
@GetMapping("/runquery")
@ResponseBody
//Changed (Change Return type to GenericResponse )
public GenericResponse runQuery(@RequestParam(name = "queryId") String queryId, @RequestParam(name = "formData") String formData, HttpServletResponse response) throws IOException {
try {
//Your code
}
} catch (Exception e) {
//Changed (Create GenericResponse for Exception)
GenericResponse genericResponse = exceptionConverter.convert(e);
return genericResponse;
}
//Changed (Create GenericResponse for main result)
return GenericResponse.ok().payload(queryResultFinal);
}
}
两个场景的示例:第一个没有例外,第二个有例外
样本1
控制器与GenericResponse我们在这个示例中没有例外
@RestController
public class TestController {
@GetMapping(value = "/getNameAndFamily")
public GenericResponse getNameAndFamily() {
Map<String, String> person = new HashMap<>();
person.put("name", "foo");
person.put("family", "bar");
return GenericResponse.ok().payload((Serializable) person);
}
}
样本2
当我们在业务中遇到异常时,具有一般响应的控制器
@RestController
public class TestController {
@Autowired
private ExceptionConverterService exceptionConverter;
@GetMapping(value = "/getNameAndFamily")
public GenericResponse getNameAndFamily() {
try {
//Create Fake Exception
int i = 1 / 0;
return GenericResponse.ok();
} catch (Exception e) {
//Handle Exception
GenericResponse genericResponse = exceptionConverter.convert(e);
return GenericResponse.ok().payload((Serializable) genericResponse);
}
}
}
结果如下:
{
"error": false,
"payload": {
"name": "foo",
"family": "bar"
}
}
{
"error": true,
"errorPayload": [
{
"errorType": "ArithmeticException"
}
]
}
如果在获取try-catch块中的数据时发生问题,我有一个响应。setStatus400-4xx错误用于与客户端相关的问题,您应该返回5xx。也许最好让异常传播并通过@ControllerAdvice连接exceptionmapper这不是Serializable的目的。Serializable用于Java二进制序列化,它既不用于也不需要用于json的序列化。使用Object作为payload方法的参数类型就足够了。
{
"error": false,
"payload": {
"name": "foo",
"family": "bar"
}
}
@RestController
public class TestController {
@Autowired
private ExceptionConverterService exceptionConverter;
@GetMapping(value = "/getNameAndFamily")
public GenericResponse getNameAndFamily() {
try {
//Create Fake Exception
int i = 1 / 0;
return GenericResponse.ok();
} catch (Exception e) {
//Handle Exception
GenericResponse genericResponse = exceptionConverter.convert(e);
return GenericResponse.ok().payload((Serializable) genericResponse);
}
}
}
{
"error": true,
"errorPayload": [
{
"errorType": "ArithmeticException"
}
]
}