“No primary or single unique constructor found for interface javax.servlet.http.HttpSession”Bug修复,javax.servlet.http.HttpSession接口无主要或唯一构造函数错误修复指南

马肤

温馨提示:这篇文章已超过464天没有更新,请注意相关的内容是否还可用!

摘要:针对“No primary or single unique constructor found for interface javax.servlet.http.HttpSession”这一Bug,表示在尝试使用HttpSession接口时遇到了构造器问题。修复此问题通常需要检查代码中是否正确实现了HttpSession接口,并确保在创建实现类时提供了正确的构造方法。可能需要检查相关的servlet配置或代码逻辑,确保符合Java Servlet规范,以正确初始化HttpSession对象。

Bug复现

今天在写SpringBoot应用时,写一个后端生成图形验证码的业务时,需要用到session保存后端生成的图形验证码的Base64编码,然后前端通过session来显示图形验证码。

代码里用到了servlet里的HttpSession类,于是idea自动导入了javax.servlet包里的HttpSession。

业务代码如下:

package cn.edu.wit.controller;
import cn.edu.wit.entity.Result;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
// 注意这里导入的是javax.servlet包
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import javax.imageio.ImageIO;
@Slf4j
@RestController
public class CaptchaController {
    private DefaultKaptcha captchaProducer;
    public CaptchaController() {
        // 配置Kaptcha
        captchaProducer = new DefaultKaptcha();
        captchaProducer.setConfig(new Config(new java.util.Properties()));
    }
    @GetMapping("/captcha")
    public Result getCaptcha(HttpSession session) throws Exception {
        // 生成验证码文本
        String captchaText = captchaProducer.createText();
        log.info("验证码: " + captchaText);
        // 将验证码文本存储在Session中
        session.setAttribute("captcha", captchaText);
        // 生成验证码图片
        BufferedImage image = captchaProducer.createImage(captchaText);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", outputStream);
        // 转换为Base64
        String base64Image = Base64.getEncoder().encodeToString(outputStream.toByteArray());
        // 返回给前端Base64编码的图形验证码
        return Result.success("data:image/jpeg;base64," + base64Image);
    }
}

Postman 测试如下:

GET http://localhost:8080/captcha

启动SpringBoot应用后,测试Postman接口,idea控制台报错:

java.lang.IllegalStateException: No primary or single unique constructor found for interface javax.servlet.http.HttpSession
	at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:267)
	at org.springframework.validation.DataBinder.createObject(DataBinder.java:924)
	at org.springframework.validation.DataBinder.construct(DataBinder.java:903)
	at org.springframework.web.bind.ServletRequestDataBinder.construct(ServletRequestDataBinder.java:116)
	at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.constructAttribute(ServletModelAttributeMethodProcessor.java:156)
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:148)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:225)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:178)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:917)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:829)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:842)

Bug原因

从stackoverflow社区找到了错误原因和解决方案

错误原因原文如下:

Spring Boot 3 (and Spring Framework 6) require a baseline of Jakarte EE 10. You cannot use it with Java EE or Jakarte EE versions below that.

You have to remove the explicit dependency on jakarta.servlet-api from your pom.xml. Java Servlet 4 is below the baseline and in particular still uses the package names starting with javax.servlet.

中文机翻:

Spring Boot 3(和 Spring Framework 6)需要 Jakarte EE 10 的基线。您不能将其与 Java EE 或低于该版本的 Jakarte EE 版本一起使用

您必须jakarta.servlet-api从您的pom.xml. Java Servlet 4 低于基线,特别是仍然使用以javax.servlet.

也就是说:SpringBoot3已经不支持javax.servlet包里的HttpSession了,如果需要使用该类的话,需要导入jakarta.servlet包里的HttpSession。

Bug修复

原作者给出的解决方案如下:

If you remove the explicit dependency, Spring will pull in transitively the correct one. You then need to replace all imports starting with javax.servlet with javax replaced by jakarta, e.g.

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;

 bug修复方法很简单,就是将所有的javax.servlet包替换成jakarta.servlet包。

例如我的代码里就应该这样修改:

// import javax.servlet.http.HttpSession;
// 将javax替换成jakarta
import jakarta.servlet.http.HttpSession;

修改后,重新运行SpringBoot应用即可正常生成图形验证码,并保存到session里返回给前端。

“No primary or single unique constructor found for interface javax.servlet.http.HttpSession”Bug修复,javax.servlet.http.HttpSession接口无主要或唯一构造函数错误修复指南 第1张

“No primary or single unique constructor found for interface javax.servlet.http.HttpSession”Bug修复,javax.servlet.http.HttpSession接口无主要或唯一构造函数错误修复指南 第2张

参考资料

Fix "No primary or single unique constructor found for interface javax.servlet.http.HttpServletResponse" in Spring Boot application


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码