Grails 3.x及3.2.5版本:如何将JSON视图输出写入文件而非HTTP响应流
在Grails 3(包括3.2.5版本)里要把JSON视图的输出写到文件而不是直接返回给HTTP响应?我给你两种实用的方案,都是项目里常用的:
方法一:用
ViewRenderingService手动渲染视图(推荐) 这是最直接且优雅的方式,Grails内置了ViewRenderingService可以帮我们直接渲染视图并获取内容,完全不需要绕响应流的弯子。
步骤很清晰:
- 先在控制器里注入这个内置服务
- 准备好JSON视图需要的模型数据
- 调用服务的
render方法渲染视图,拿到字符串格式的JSON结果 - 用Groovy的文件API把内容写入目标文件
代码示例:
import grails.views.rendering.service.ViewRenderingService class BookController { // 注入Grails内置的视图渲染服务 ViewRenderingService viewRenderingService def exportToFile() { // 1. 准备模型数据,这里以查询单个Book实例为例 def bookInstance = Book.get(1) def model = [book: bookInstance] // 2. 渲染JSON视图: // 视图路径对应grails-app/views/book/show.json.gson // 如果是当前控制器的视图,也可以简化成view: 'show' String jsonOutput = viewRenderingService.render( view: '/book/show', model: model, contentType: 'application/json' ) // 3. 写入文件,这里用项目根目录作为输出位置,你可以自定义路径 def targetFile = new File("${System.getProperty('user.dir')}/book-output.json") targetFile.text = jsonOutput // 给前端返回操作结果提示 render "JSON内容已成功写入文件:${targetFile.absolutePath}" } }
方法二:捕获响应输出流(备选方案)
如果因为某些场景限制不想用ViewRenderingService,也可以通过临时替换HTTP响应的输出流,捕获渲染后的内容再写入文件。这种方法要注意务必恢复原来的输出流,否则会影响后续的请求响应。
代码示例:
class BookController { def exportToFile() { def bookInstance = Book.get(1) // 先保存原来的响应输出流 def originalOutputStream = response.outputStream try { // 创建字节数组输出流来捕获渲染内容 def byteStream = new ByteArrayOutputStream() response.outputStream = byteStream // 正常渲染JSON视图,此时内容会写到byteStream里而不是前端 respond bookInstance, [view: 'show', format: 'json'] response.flushBuffer() // 把捕获到的内容转成UTF-8格式的字符串 String jsonContent = byteStream.toString('UTF-8') // 写入目标文件 def targetFile = new File("book-output.json") targetFile.text = jsonContent // 给前端返回提示(需要用原来的输出流) originalOutputStream.write("操作完成,JSON已写入文件".getBytes('UTF-8')) } finally { // 务必恢复原来的输出流,否则后续请求会出问题 response.outputStream = originalOutputStream } } }
一些注意事项
- 文件路径:如果是部署到服务器,尽量用绝对路径,避免因工作目录变化导致找不到文件的问题。比如可以通过Grails配置项指定输出目录,或者用
grailsApplication.mainContext.getResource('file:./outputs/').file来获取项目下的固定目录。 - 权限:确保应用程序对目标文件所在目录有写入权限,否则会抛出IO异常。
- 视图路径:渲染视图时,以
/开头的是绝对路径(从grails-app/views根目录开始找);相对路径则是当前控制器对应的视图目录。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

