如何在Spring ModelAttribute中将字节数组转换为字符串?
嗨,这个问题我之前做CKEditor集成的时候也遇到过,其实核心就是要在Spring数据绑定和数据库交互的环节,把字节数组和字符串做无缝转换,结合你的场景,有几个实用的解决办法:
方案一:给实体类加辅助属性(最省心的快速方案)
不用改动太多业务代码,只需要在Post类里新增一个字符串类型的辅助属性,通过它的getter/setter自动完成和原byte[]属性的转换,完美适配Spring表单的modelAttribute绑定:
import java.nio.charset.StandardCharsets; public class Post{ private byte[] postContent; // 新增辅助属性,专门给Spring表单绑定用 private String postContentStr; // 原byte[]属性的getter/setter,保持给数据库操作使用 public byte[] getPostContent() { return postContent; } public void setPostContent(byte[] postContent) { this.postContent = postContent; // 从数据库取出字节数组时,自动转成UTF-8字符串赋值给辅助属性 if (postContent != null) { this.postContentStr = new String(postContent, StandardCharsets.UTF_8); } } // 辅助属性的getter/setter,给Spring表单绑定用 public String getPostContentStr() { return postContentStr; } public void setPostContentStr(String postContentStr) { this.postContentStr = postContentStr; // 表单提交字符串时,自动转成UTF-8字节数组赋值给原属性 if (postContentStr != null) { this.postContent = postContentStr.getBytes(StandardCharsets.UTF_8); } } }
然后修改JSP里的表单标签,把path指向新增的辅助属性:
<form:form ...... modelAttribute="post"> ... <form:textarea path="postContentStr" id="editor1"> .... </form:form>
这样不管是从数据库取数据回显,还是表单提交保存,转换都会自动完成,控制器代码完全不用改。
方案二:在控制器层手动处理转换(适合不想改实体类的场景)
如果不想修改实体类结构,可以在从数据库取数据后,手动把字节数组转成字符串放到Model里,回显时用普通文本域而非Spring表单标签:
回显数据时的控制器代码:
import java.nio.charset.StandardCharsets; // ... Post post = postService.findByPostId(postId); if (post != null) { mv.addObject("title", "Edit Post"); // 把字节数组转成UTF-8字符串,单独放到Model中 if (post.getPostContent() != null) { String contentStr = new String(post.getPostContent(), StandardCharsets.UTF_8); mv.addObject("postContentStr", contentStr); } mv.addObject("post", post); // ... }
JSP里的回显代码:
<form:form ...... modelAttribute="post"> ... <!-- 用普通textarea,直接通过EL表达式赋值回显内容 --> <textarea id="editor1" name="postContent">${postContentStr}</textarea> .... </form:form>
表单提交时的控制器处理:
提交时需要把接收的字符串转成字节数组再赋值给Post对象:
@RequestMapping(value = "/edit", method = RequestMethod.POST) public String editPost(@ModelAttribute("post") Post post, @RequestParam("postContent") String content) { post.setPostContent(content.getBytes(StandardCharsets.UTF_8)); postService.updatePost(post); return "redirect:/posts"; }
方案三:全局注册类型转换器(最优雅的Spring风格方案)
如果项目里有很多类似的byte[]和String互转场景,可以自定义Spring转换器,让框架自动处理类型转换,完全不用改动实体类和表单代码:
第一步:定义转换器类
import org.springframework.core.convert.converter.Converter; import java.nio.charset.StandardCharsets; // 字节数组转字符串 public class ByteArrayToStringConverter implements Converter<byte[], String> { @Override public String convert(byte[] source) { return source == null ? null : new String(source, StandardCharsets.UTF_8); } } // 字符串转字节数组 public class StringToByteArrayConverter implements Converter<String, byte[]> { @Override public byte[] convert(String source) { return source == null ? null : source.getBytes(StandardCharsets.UTF_8); } }
第二步:注册转换器到Spring容器
创建一个Web配置类,把转换器注册进去:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new ByteArrayToStringConverter()); registry.addConverter(new StringToByteArrayConverter()); } }
做完这两步,你原来的实体类和表单代码完全不用改,Spring会自动在表单绑定和数据流转时完成byte[]和String的互转,非常优雅!
重要提醒
不管用哪种方案,一定要显式指定字符集(比如StandardCharsets.UTF_8),避免因为环境默认字符集不同导致的乱码问题。
内容的提问来源于stack exchange,提问作者DJSarma
相关产品推荐
相关产品推荐

