RESTful接口请求不存在资源却返回响应的问题排查
问题分析与解决:请求不存在的Message ID返回错误数据
嘿,我一眼就揪出问题根源了!你的list是静态(static)成员变量,但你却在MessageResource的构造方法里,每次都往这个静态列表里添加那三条Message实例。
为什么会出现这种情况?
在JAX-RS框架(比如你用的Jersey)里,默认的资源类实例化策略是每处理一个请求就创建一个新的资源类实例。这意味着每来一个请求,MessageResource的构造方法就会执行一次——而因为list是静态的,所有实例共享同一个列表,所以每次构造方法执行都会往列表里重复塞三次那三条消息。
举个例子:
- 第一次请求(比如
/1):构造方法执行,列表变成[m1, m2, m3],返回m1,一切正常。 - 第二次请求(比如
/2):新的MessageResource实例被创建,构造方法再次执行,列表变成[m1, m2, m3, m1, m2, m3],返回m2,看起来也没问题。 - 当你请求
/4时,messageId-1 = 3,此时列表的第4个元素(索引3)就是第二次添加的m1——这就是你看到{"id":1,"message":"m1"}的原因!
怎么修复?
给你两种靠谱的修复方案:
方案1:用静态代码块初始化列表(推荐)
把列表的初始化逻辑放到静态代码块里,这样JVM加载MessageResource类时只会执行一次,彻底避免重复添加数据:
@Path("testresource") public class MessageResource { private static List<Message> list = new ArrayList<>(); // 静态代码块:类加载时仅执行一次 static { list.add(new Message(1L,"m1")); list.add(new Message(2L,"m2")); list.add(new Message(3L,"m3")); } public MessageResource() { // 构造方法里不再添加数据 } @GET @Path("{messageId}") @Produces(MediaType.APPLICATION_JSON) public Message getSpecificMessage(@PathParam("messageId") int messageId) { // 额外优化:先判断请求的ID是否在有效范围内,避免抛出索引越界异常 if (messageId < 1 || messageId > list.size()) { // 抛出WebApplicationException,让框架返回404(资源不存在)响应 throw new WebApplicationException(Response.Status.NOT_FOUND); } return list.get(messageId-1); } }
方案2:调整资源类作用域为单例
如果你想保留构造方法里的初始化逻辑,可以给MessageResource添加@Singleton注解,让框架只创建一个实例,这样构造方法只会执行一次:
@Singleton @Path("testresource") public class MessageResource { private List<Message> list = new ArrayList<>(); public MessageResource() { list.add(new Message(1L,"m1")); list.add(new Message(2L,"m2")); list.add(new Message(3L,"m3")); } // 后续方法同之前,记得加上ID有效性判断 }
额外提醒
你当前的代码还有个小隐患:如果请求的ID超过列表长度(比如5、6),会直接抛出IndexOutOfBoundsException,框架可能返回500服务器错误——这不符合RESTful规范。建议像方案1里那样,先校验ID的有效性,返回404(资源不存在)的响应,更合理。
内容的提问来源于stack exchange,提问作者Gaurav Kumar
相关产品推荐
相关产品推荐

