【低效编码】一个@ResponseBody注解没加让我这个菜鸟原形毕露

【低效编码】一个@ResponseBody注解没加让我这个菜鸟原形毕露小问题暴露大知识点

大家好,又见面了,我是你们的朋友全栈君。

您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧。小伙伴们,有啥想看的,想问的,欢迎积极留言告诉我喔。
今天是5月12日,太阳依然比我起的更早一些。8点半闹铃准时响起来,一把将我从黄粱美梦中拉回到了现实中来,我猛地从床上弹起来(枕边没人,害,可怜人儿),急匆匆洗漱完,挂上工牌,背起小米双肩包,穿上那件心爱的格子衫,就开启了一天的搬砖之旅。
在这里插入图片描述

开心编码

事情是这样的,我在用SpringBoot框架搭建的项目上写了一个新增用户的接口,接口地址是/v1/user/test,代码如下所示(demo版,非生产代码),简单到不能再简单的一个接口,像这样的接口我都记不清自己已经写了多少个了。

@Controller
public class TestRespController { 
   
	//新增用户的接口
    @RequestMapping("/v1/user/test")
    public User addUser(String userName, String password) { 
   
        User user = new User();
        user.setUserName(userName);
        user.setPassword(password);
        return user;
    }
}

接口写好之后,我没有多想,就启动项目开始调试代码,我熟练的在chrome浏览器上输入了http://localhost:8080/v1/user/test 这个地址,然后点击回车,没想到的是页面上提示了一个404的错误。
在这里插入图片描述
这是怎么回事呢?我这接口地址没有错呀,为啥找不到接口呢?奇了怪了。我火急火燎的跑到控制台,看看有没有错误日志。让我很失望啥错误都没有输出,过滤器也准确的把我的输入的请求地址打印出来了。
在这里插入图片描述

苦苦寻找

为啥页面报了404的错误,而控制台没有任何错误输出呢?实在是有点诡异。问同事嘛,又不好意思,自己好歹是个高级开发工程师,404的问题都搞不定实在是说不过去。三十六计走为上,看看其他的正常的接口是怎么写的。然后,我找到了这样一个接口,这个接口是可以正常访问的,

    @ResponseBody
    @RequestMapping("/v1/user/test/update")
    public User updateUser(User user) { 
   
        boolean result = testNgService.updateUser(user);
        return result ? user : null;
    }

哦哦哦,我突然恍然大悟,原来是没有在接口上添加@ResponseBody 注解,我印象中这个注解可以将返回的对象序列化成json字符串,并放在响应体中,但是跟接口地址又有啥关系呢?。抱着试试看的态度,我在接口上加上了 @ResponseBody注解,代码就不列举了,太简单了不好意思列举。再次访问http://localhost:8080/v1/user/test 这个地址,接口可以正常返回数据了。
在这里插入图片描述
当然,如果该类下所有的接口都是返回application/json格式数据的接口,则可以直接将类上的**@Controller注解替换成 @RestController 注解。@RestController注解是一个组合注解是由@Controller注解和@ResponseBody注解组成**。

思考升华

至此,问题是解决了。但是,心中的小问号还萦绕在心头。

  1. 为啥页面报了404的错误,但是控制台没有错误日志呢?
  2. 为啥不加@ResponseBody注解接口会报404的错误呢?
    知道的小伙伴,可以在下方评论留言哦,并且直接略过下面的内容,因为你们太牛逼了。

有问题,咱们就解决问题,(而不是解决提出问题的人喔,哈哈哈哈)

1. 为啥页面报了404的错误,但是控制台没有错误日志呢?

为啥出现了404的异常,但是控制台没有错误的日志输出呢?这个就很奇怪了。这个问题是我们首先需要解决的,不然不知道具体的错误是啥,就很难定位到问题。根据已经掌握SpringMVC的知识:我们在页面输入一个url之后,请求首先会到DispatcherServlet。然后,DispatcherServlet会根据url去HandelMapping中找到能处理该请求的Handler。如果找不到的话则会报错404的错误,所以,猜测SpringBoot抛出的是NoHandlerFoundException这个异常,现在的问题就是为啥这个NoHandlerFoundException没输出呢?一番百度之后,我发现只需要在配置文件application.yml中添加如下配置即可:

spring:
  mvc:
# 允许抛出NoHandlerFoundException
    throw-exception-if-no-handler-found: true
# 禁用资源映射
  resources:
    add-mappings: false

加上这两个配置之后,在访问接口的话,控制台就会打印出如下的错误日志:我们看到在查找mapping时url就变成了 /v1/user/v1/user/test,不是我们期待的 /v1/user/test
在这里插入图片描述
说明:加上spring.resources.add-mappings=false 禁用资源映射之后,可以输出

o.s.web.servlet.PageNotFound             : No mapping for GET /v1/user/v1/user/test

springboot中的WebMvcAutoConfiguration类配置默认资源映射地址是 “/”

private static final String SERVLET_LOCATION = "/";

即使你的地址错误也会匹配到 /** 这个静态资源映射地址,就不会进入noHandlerFound方法,自然不会抛出NoHandlerFoundException了。
异常终于暴露出来了。接下来就是处理异常了。

2. 为啥不加@ResponseBody注解接口会报404的错误呢?

要想回答这个问题,还是要回到 @ResponseBody 注解的作用上面,一番苦苦的搜索之后,我终于发现了答案。@ResponseBody 注解的作用就是将Controller返回的对象通过适当的HttpMessageConverter转换为指定的格式,写入到Response对象的body数据区中返回给前端页面。如果没有加这个注解,只有@RequestMapping这个注解的话,则返回值通常解析为跳转路径,控制器返回的时候路径会变为(在当前路径的上一级路径上追加路径),然后返回的过程找不到对应的视图,导致404的错误。这只是理论,实际上是不是这样子的呢?还需要我们验证一下。

  1. 不加@ResponseBody则默认会返回一个视图,如下图所示,返回一个名为 /static/helloWorld.html的视图。
    @RequestMapping("/v1/user/test1")
    public String queryUserHtml2() { 
   
        return "/static/helloWorld.html";
    }

即会访问static目录下的helloWorld.html页面。
在这里插入图片描述
访问结果是:
在这里插入图片描述
页面可以正常的跳转,说明,不加上@ResponseBody注解确实会默认返回一个视图,这是正常的能找到页面的视图,如果返回一个不存在的视图会怎样呢?

    @RequestMapping("/v1/user/test2")
    public String queryUserHtml3() { 
   
        return "{\"code\":200}";
    }

打印出来的路径是 /v1/user/{“code”:200},即/v1/user/test2的上级路径 /v1/user+{“code”:200},说明上面的理论解释是没有问题的。

总结

本文从实际开发中一个很小的问题入手,层层分析问题的根源,知其然更要知其所以然。总之,一句话总结@ResponseBody注解的作用就是将返回的结果通过HttpMessageConverter 转换为指定格式并放在响应体中,没有它的话,SpringBoot会默认返回一个视图。

参考

@ResponseBody注解
解决springboot配置@ControllerAdvice不能捕获NoHandlerFoundException问题

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140224.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql语句大全及例子_SQL语句大全实例教程.pdf[通俗易懂]

    mysql语句大全及例子_SQL语句大全实例教程.pdf[通俗易懂]SQL语句大全实例教程无论您是一位SQL的新手,或是一位只是需要对SQL复习一下的资料仓储业界老将,您就来对地方了。这个SQL教材网站列出常用的SQL指令,包含以下几个部分:♦SQL指令:SQL如何被用来储存、读取、以及处理数据库之中的资料。♦表格处理:SQL如何被用来处理数据库中的表格。♦进阶SQL:介绍SQL进阶概念,以…

    2022年5月20日
    36
  • 在线html代码生成器,支持网页快速排版 CSS代码一键生成的在线设计工具

    在线html代码生成器,支持网页快速排版 CSS代码一键生成的在线设计工具用户体验现在作为很多工作的重中之重,设计师们更要把用户体验放在第一位,如果你曾经尝试过想把你的板面调整到最适合阅读的状态,就会知道多么令人抓狂。但是懒人总是会创造出新科技,国外开发者为我们带来了今天要讲的协助设计网页排版及字型等相关属性的便利工具。typeanything前段时间登上国外媒体网站后深获好评,这是一项非常方便的在线工具,功能设计很简单,主要提供一段文章模板(里头包含h1、h2…

    2022年5月11日
    131
  • SpringBoot:简述SpringBoot和Spring的区别

    SpringBoot:简述SpringBoot和Spring的区别SpringBoot:简述SpringBoot和Spring的区别一、Spring的介绍   简而言之,Spring框架为开发Java应用程序提供了全面的基础架构支持。它包含一些很好的功能,如依赖注入和开箱即用的模块,如:SpringJDBCSpringMVCSpringSecuritySpringAOPSpringORMSpring…

    2022年4月28日
    148
  • 毕业5年,我问遍了身边的大佬,总结了他们的学习方法

    毕业5年,我问遍了身边的大佬,总结了他们的学习方法我问了身边10个大佬,总结了他们的学习方法,原来成功都是有迹可循的。

    2022年6月10日
    25
  • 【笔记】EFCore & SQLite 拼音汉字互换

    【笔记】EFCore & SQLite 拼音汉字互换1vs2019新建.netcoreconsole项目,NuGet添加包Microsoft.EntityFrameworkCore//efcoreMicrosoft.EntityFrameworkCore.Design//在nugetMicrosoft.EntityFrameworkCore.Tools//控制台中管理数据迁移Microsoft.EntityFrameworkCore.Sqlite//sqliteM.

    2022年6月21日
    24
  • android读取sqlite数据库的数据并用listview显示

    android读取sqlite数据库的数据并用listview显示android读取sqlite数据库的数据并用listview显示刚刚接触android,老师给了我了几个班级信息的excel,让我做一个考勤的系统出来,本篇仅记录了真机调试下,读取已有静态数据库信息并显示在listview中。准备工作开发工具为AndroidStudio。sqlite可视化软件SQLiteExpertProfessional5已将excel表转化为的数据库student1………

    2022年7月27日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号