【低效编码】一个@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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python之contextlib库及源码分析建议收藏

    AbstractContextManager(abc.ABC)上下文管理抽象类,子类必须实现__enter__(self)、__exit__(self)ContextDecorator(objec

    2021年12月19日
    46
  • access token

    最短时间来,打算把自己学习的东西都总结一遍,发到博客上面来。带大家来了解windows访问令牌0x00acesstoken的作用accesstoken的作用说简单点就是为了系统的安全0x

    2021年12月11日
    106
  • ipfs是什么挖矿机制(目前最好的ipfs矿机)

    尽管近期市场正在复苏,但FIL仍在50U左右波动,并未出现太大波动,许多投资者都望而却步。IPFS/FIL不错。为什么货币价格不上涨?这种现象其实已经不正常了,价格的波动和数据的修改都不可能在正常的情况下处于正常的状态,相信华雷新山不会出现任何数字货币的不涨不跌,以前的程序员10年5月btc1万现在10。1000个比特币相当于4亿u。11年过去了,现在还不知道哪位程序员。btc用了将近11年的时间才证明了它的价值。对今天的大多数普通人来说,这是一个不能实现的梦想。eth的概念最初是Vita.

    2022年4月14日
    67
  • 分享一个二次元动漫视频网站源码「建议收藏」

    分享一个二次元动漫视频网站源码「建议收藏」源码下载地址:下载地址非常大气漂亮的Miko动漫视频网站整站源码,二次元动漫网源码。Dz后台管理方便,整站数据都设置好了,传上即可制作一个完整的动漫网。1.源码上传到空间2.把数据库文件.sql上传到数据库里3.后台域名/admin.php4.账号liujianghao密码miko2016…

    2022年8月23日
    16
  • FTP协议讲解

    FTP协议讲解FTP概述文件传输协议(FTP)作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用。FTP的目标是提高文件的共享性和可靠高效地传送数据。在传输文件时,FTP客户端程序先与服务器建立连接,然后向服务器发送命令。服务器收到命令后给予响应,并执行命令。FTP协议与操作系统无关,任何操作系统上的程序只要符合FTP协议,就可以相互传输数据。本文主要基于LINUX平台,对FTP…

    2022年6月21日
    26
  • dmesg命令「建议收藏」

    dmesg命令「建议收藏」Linuxdmesg命令 Linux命令大全Linuxdmesg命令用于显示开机信息。kernel会将开机信息存储在ringbuffer中。您若是开机时来不及查看信息,可利用dmesg来查看。开机信息亦保存在/var/log目录中,名称为dmesg的文件里。语法dmesg[-cn][-s]参数说明:-c 显示信息后,清除ri

    2025年8月4日
    3

发表回复

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

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