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


相关推荐

  • 深入理解Java注解类型(@Annotation)[通俗易懂]

    深入理解Java注解类型(@Annotation)[通俗易懂]【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)http://blog.csdn.net/javazejian/article/details/71860633出自【zejian的博客】关联文章:深入理解Java类型信息(Class对象)与反射机制深入理解Java枚举类型(enum)深入理解Java注解类型(@Annotation)深入理解

    2022年7月8日
    26
  • Java 中的 StringBuilder 类的常用方法

    Java 中的 StringBuilder 类的常用方法StringBuilder类提供了很多方法来操作字符串:例如:在下面的示例代码中,创建了StringBuilder对象,用来存储字符串,并对其做了追加和插入操作。这些操作修改了str对象的值,而没有创建新的对象,这就是StringBuilder和String最大的区别。运行结果: …

    2022年7月17日
    19
  • LMDB笔记_pdf怎么做笔记

    LMDB笔记_pdf怎么做笔记作为一个计算机底层小白,在了解一个知识点的时候时常需要恶补很多基础知识。本文记录在了解LMDB过程中接触的知识点。LMDB基本架构一个比较官方的解释:lmdb的基本做法是使用mmap文件映射,不管这个文件存储实在内存上还是在持久存储上。lmdb的所有读取操作都是通过mmap将要访问的文件只读的映射到虚拟内存中,直接访问相应的地址.因为使用了read-only的mmap,同样避免了程序错误将存…

    2022年9月29日
    4
  • git无法删除本地分支_git如何删除远程分支

    git无法删除本地分支_git如何删除远程分支git删除本地分支出现错误转载:https://blog.csdn.net/benben_2015/article/details/79782202删除本地分支经常出现的情况有以下几种:error:Thebranch‘testing’isnotfullymerged.使用gitbranch-dtestin…

    2022年10月10日
    3
  • 深度学习 — BP算法详解(误差反向传播算法)「建议收藏」

    深度学习 — BP算法详解(误差反向传播算法)「建议收藏」本节开始深度学习的第一个算法BP算法,本打算第一个算法为单层感知器,但是感觉太简单了,不懂得找本书看看就会了,这里简要的介绍一下单层感知器:图中可以看到,单层感知器很简单,其实本质上他就是线性分类器,和机器学习中的多元线性回归的表达式差不多,因此它具有多元线性回归的优点和缺点。单层感知器只能对线性问题具有很好的解决能力,但是非线性问题就无法解决了,但是多层感知器却可以解决非线性问题,多层感…

    2022年5月3日
    96
  • FindWindowEx的应用

    FindWindowEx的应用HWND hWorker,hRebar,hComEx,hcom,hEdit;HWND hwndParent=::FindWindow("IEFrame",NULL);//找到IE窗口  char szError[260];hWorker=FindWindowEx(hwndParent,0,"WorkerA",NULL);//找到工作区窗口(不是internet e…

    2022年5月30日
    33

发表回复

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

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