首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring问题汇总

Spring问题汇总

作者头像
雨临Lewis
发布2022-01-12 11:34:22
发布2022-01-12 11:34:22
6630
举报
文章被收录于专栏:雨临Lewis的博客雨临Lewis的博客

SpelEvaluationException: EL1030E

运行Spring项目时报错如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

org.springframework.expression.spel.SpelEvaluationException: EL1030E: The operator 'ADD' is not supported between objects of type 'java.lang.String' and 'null' at org.springframework.expression.spel.ExpressionState.operate(ExpressionState.java:240) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:80) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:85) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:83) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:83) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:83) at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:83) at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:109) at org.springframework.expression.spel.standard.SpelExpression.getValue .... at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

从堆栈信息可以看出,该异常与spel有关。spel指的是Spring Expression Language,结合问题代码进行分析,可以认为该异常与spring表达式有关。而在我的代码里,只有@Cacheable注解里使用到了spel,如下:

1 2 3 4 5 6

@Cacheable(key = "#root.target.getCacheKeyPrefix() + '::' + + #root.target.getRootDomain() + '-' + #root.target.getLocale() + '-' + #searchLabelKey") public String getFromRootDomain(final String labelId, final String locale, final String searchLabelKey) { // TODO return null; }

很显然,在使用到该注解时,由于这里的spring表达式有问题,最终在解析时抛出了异常。经过检查发现,这里犯了个很逗的错误,就是连续使用了两个+,导致解析无法通过,改正后如下:

1

@Cacheable(key = "#root.target.getCacheKeyPrefix() + '::' + #root.target.getRootDomain() + '-' + #root.target.getLocale() + '-' + #searchLabelKey")

而之所以之前没能发现这个问题,是因为没有启用redis cache,导致避开了这个问题。目前刚开始了解spel这门表达式语言,在此记录下这个问题,方便日后回顾分析,参考链接里顺便贴上官方的一篇中译文档。

@PathVariable会截断字符串中最后一个.

当使用了@PathVariable接收参数时,如果该参数的值包含有.这个符号,则最后的.以及之后的字符串会被截断。举个简单的例子,代码如下:

1 2 3 4 5

@GetMapping(value = "/users/{loginId}", produces = Constants.REQUEST_BODY_TYPE_APP_JSON) public UserDto getLatestUserByLoginId(@PathVariable final String loginId) throws DocumentNotFoundException { final UserDto result = userDocumentService.findDtoByLoginIdAndIsLatest(loginId); return result; }

  • 当请求是/users/lewis.liu时,loginId参数接收到的值是lewis
  • 当请求是/users/lewis.liu.p时,loginId参数接收到的值是lewis.liu
  • 当请求是/users/lewis.liu.p.w时,loginId参数接收到的值是lewis.liu.p

可以发现,@PathVariable注解会自动截断最后一个.以及之后的字符串。这是因为Spring认为最后一个.以及之后的字符串属于文件扩展类型,比如.java之类的,所以就自动将其截断了。

解决这个问题可以在请求的变量占位符里加上正则表达式,如下:

1 2 3 4 5

// 原来的写法 @GetMapping(value = "/users/{loginId}", produces = Constants.REQUEST_BODY_TYPE_APP_JSON) // 改后的写法 @GetMapping(value = "/users/{loginId:.+}", produces = Constants.REQUEST_BODY_TYPE_APP_JSON)

获取当前项目部署在Tomcat中的路径

1 2 3 4 5 6 7 8

import javax.servlet.ServletContext; import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); ServletContext servletContext = webApplicationContext.getServletContext(); String contextPath = servletContext.getContextPath();

参考链接

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-092,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpelEvaluationException: EL1030E
  • @PathVariable会截断字符串中最后一个.
  • 获取当前项目部署在Tomcat中的路径
  • 参考链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档