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()重置状态:
- 添加配置类注册Bean:
@Configuration public class DigestConfig { @Bean public MessageDigest sha256Digest() throws NoSuchAlgorithmException { return MessageDigest.getInstance("SHA-256"); } }
- 修改控制器通过构造方法注入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
相关产品推荐
相关产品推荐

