You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring使用MessageDigest遇NoSuchMethodException问题求助

问题分析与解决方案

错误原因

控制台抛出java.lang.NoSuchMethodException: java.security.MessageDigest.<init>()的核心原因是:
Spring MVC处理请求时,会自动解析控制器方法的参数。你的myHash方法将MessageDigest作为参数,Spring默认把它当作@ModelAttribute类型参数,尝试调用其无参构造方法创建实例,但MessageDigest只能通过静态工厂方法getInstance()实例化,没有公共无参构造,因此触发异常。

你在主方法中手动创建MessageDigest实例并调用myHash的逻辑无效,因为Spring管理的Controller实例和你手动new的不是同一个,请求/hash时Spring会自己调用方法并尝试解析参数。

解决方案

方案1:在控制器方法内部实例化MessageDigest(推荐)

将MessageDigest的创建逻辑移到myHash方法内部,无需外部传参,同时移除主方法中手动调用Controller的代码:

修改后的主类:

@SpringBootApplication
public class SslServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SslServerApplication.class, args);
    }
}

修改后的控制器:

@RestController
class ServerController{
    // 哈希函数,返回字符串数据的校验和值
    @RequestMapping("/hash")
    public String myHash() throws NoSuchAlgorithmException {
        String data = "myName";
        // 待哈希的数据
        
        // 直接在方法内创建MessageDigest实例
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digested = md.digest(data.getBytes());
        
        String hexdata = bytesToHex(digested);
        // 将哈希值转换为十六进制
        
        return "<p>data: myName, SHA-256" + hexdata;
        // 返回十六进制结果
    }
    
    // 将字节转换为十六进制
    private String bytesToHex(byte[] digested) {
        StringBuilder sb = new StringBuilder();
        for (byte hashByte : digested) {
            int intVal = 0xff & hashByte;
            if (intVal < 0x10) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(intVal));
        }
        return sb.toString();
    }
}

方案2:注册MessageDigest为Spring Bean(需注意线程安全)

如果需要在多个方法中复用MessageDigest,可以将其注册为Spring Bean,但要注意MessageDigest不是线程安全的,每次使用前必须调用reset()重置状态:

  1. 添加配置类注册Bean:
@Configuration
public class DigestConfig {
    @Bean
    public MessageDigest sha256Digest() throws NoSuchAlgorithmException {
        return MessageDigest.getInstance("SHA-256");
    }
}
  1. 修改控制器通过构造方法注入Bean:
@RestController
class ServerController{
    private final MessageDigest messageDigest;

    // 构造方法注入MessageDigest实例
    public ServerController(MessageDigest messageDigest) {
        this.messageDigest = messageDigest;
    }

    @RequestMapping("/hash")
    public String myHash() throws NoSuchAlgorithmException {
        String data = "myName";
        
        // 线程安全:每次使用前重置状态
        messageDigest.reset();
        byte[] digested = messageDigest.digest(data.getBytes());
        
        String hexdata = bytesToHex(digested);
        return "<p>data: myName, SHA-256" + hexdata;
    }
    
    private String bytesToHex(byte[] digested) {
        StringBuilder sb = new StringBuilder();
        for (byte hashByte : digested) {
            int intVal = 0xff & hashByte;
            if (intVal < 0x10) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(intVal));
        }
        return sb.toString();
    }
}

内容的提问来源于stack exchange,提问作者hnlt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:22:13