Velocity 有几个参数跟编码有关的分别是:
default.contentType=text/html input.encoding=GBK output.encoding=UTF-8 |
其中第一个参数指定了 velocity 模板执行后输出到浏览器时的 ContentType;第二个参数是 Velocity 引擎以什么编码方式读取 velocity 模板文件;第三个参数是输出页面的编码。
但是采用 Struts 2 后发现这三个参数并没有起作用,深入 Struts 2 的代码发现在处理 vm 编码时采用的是 Struts 2 的编码配置,而且读取 velocity 模板文件和输出 html 到浏览器采用的相同的编码,这种方式个人觉得 Struts 2 处理欠妥当,为了保留 Velocity 的特色,在 VelocityLayoutResult 的基础上进一步改进。我们需要重载 VelocityResult 的 setVelocityManager 方法,因为这个方法是用来初始化 Velocity 引擎的,我们在初始化的过程中读取前面提到的三个配置参数并把参数值保存在类的属性中,详细的代码如下:
同时修改 doExecute 方法以使用正确的编码进行处理,主要代码如下(请注意标识为粗体的代码):@Inject @Override public void setVelocityManager(VelocityManager mgr) { super.setVelocityManager(mgr); if(mgr != null && velocityManager==null){ this.velocityManager = mgr; ServletContext ctx = ServletActionContext.getServletContext(); velocityManager.init(ctx); VelocityEngine engine = velocityManager.getVelocityEngine(); defaultLayout = (String)engine.getProperty(PROPERTY_DEFAULT_LAYOUT); layoutDir = (String)engine.getProperty(PROPERTY_LAYOUT_DIR); if (!layoutDir.endsWith("/")){ layoutDir += '/'; } if (!layoutDir.startsWith("/")){ layoutDir = "/" + layoutDir; } // for efficiency's sake, make defaultLayout a full path now defaultLayout = layoutDir + defaultLayout; inputEncoding = (String)engine.getProperty(PROPERTY_INPUT_ENCODING); outputEncoding = (String)engine.getProperty(PROPERTY_OUTPUT_ENCODING); contentType = (String)engine.getProperty(PROPERTY_CONTENT_TYPE); if (outputEncoding != null && contentType != null) { contentType = contentType + ";charset=" + outputEncoding; } } }
Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, inputEncoding); Context context = createContext(velocityManager, stack, request, response, finalLocation); //将页面执行结果写入到字符串缓存中 StringWriter sw = new StringWriter(); t.merge(context, sw); context.put(KEY_SCREEN_CONTENT, sw.toString()); Object obj = context.get(KEY_LAYOUT); String layout = (obj == null) ? null : obj.toString(); if (layout == null) { // no alternate, use default layout = defaultLayout; } else { // make it a full(er) path layout = layoutDir + layout; } Template layout_vm = null; try { //System.err.println("-------------- > layout=" + layout); //load the layout template layout_vm = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, layout, inputEncoding); } catch (Exception e) { velocityManager.getVelocityEngine().getLog().error( "VelocityLayoutResult: Can't load layout \"" + layout + "\": " + e); // if it was an alternate layout we couldn't get... if (!layout.equals(defaultLayout)) { // try to get the default layout // if this also fails, let the exception go layout_vm = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, defaultLayout, inputEncoding); } } Writer writer = new OutputStreamWriter(response.getOutputStream(), outputEncoding); response.setContentType(contentType); layout_vm.merge(context, writer); writer.flush();
本文是在初步使用 Struts 2 时所发现的一些问题,通过对 Struts 2 代码的研究找出相应的解决办法,如果你在使用 Struts 2 和 Velocity 中有发现其他问题,欢迎跟我联系一起探讨。