繁体   English   中英

使用Spring MVC + Freemarker处理用户特定日期/时区转换的最佳方法

[英]Best way to handle user specific date/timezone conversion with Spring MVC + Freemarker

我想显示使用用户时区格式化的存储日期(时区为UTC) (可能因用户而异,并存储在配置文件中)。

我提出的解决方案是以下一个, 我想知道这是否是最好的方法 ,或者是否有另一个,可能更简单的解决方案。

时区设置为UTC:

-Duser.timezone=UTC

控制器,Freemarker-Template,HandlerInterceptor:

控制器:

@Controller
@RequestMapping("/test")
public class TestController {

        @RequestMapping
        public String dateTest(Model model){
                final Date date = new Date();
                model.addAttribute("formattedDate", new SimpleDateFormat("hh:mm:ss").format(date));
                model.addAttribute("date", date);              
                return "test";
        }
}

Freemarker的,模板:

<#setting time_zone="${currentTimeZone}">

UTC Time: ${formattedDate}<br/>
Localized time for timezone <i>${currentTimeZone}</i>: ${date?time}

HandlerInterceptor接口:

public class TimezoneHandlerInterceptor extends HandlerInterceptorAdapter{

        @Override
        public void postHandle(HttpServletRequest request,
                        HttpServletResponse response, Object handler,
                        ModelAndView modelAndView) throws Exception {

                //Only for testing, in production something like: 
                //final String currentUserTimezone = userService.getCurrentUser().getTimezoneId();
                final String currentUserTimezone = "Europe/Berlin";

                modelAndView.addObject("currentTimeZone", currentUserTimezone);            
        }
}

输出:

UTC Time: 08:03:53
Localized time for timezone Europe/Berlin: 09:03:53

那么是否有更标准或甚至开箱即用的方法来实现相同的结果? 谢谢你的帮助。

由于您打印两次相同的日期,只是以不同的方式呈现(不同的时区),它可能只是一个演示文稿(MVC View)问题,因此它不应该在模型中解决。 相反,你可以做这样的事情是模板:

<#import "/lib/utils.ftl" as u>
...
UTC Time: ${u.utcTime(date)}<br/>
Localized time for timezone <i>${currentTimeZone}</i>: ${date?time}

utcTime应该在utils.ftl中定义,如<#assign u = "com.something.freemarker.UtcTimeMethod"?new()> ,其中com.something.freemarker.UtcTimeMethodTemplateMethodModelEx实现。 还有其他方法可以做到这一点,比如u可能是FreeMarker配置中定义的共享变量等等。重点是,你需要打印UTC时间不会影响模型。

<#setting time_zone=currentTimeZone>部分开始(注意那里不需要${...} ),当然它取决于Web应用程序框架,但是如果你设置时区(如在调用模板之前,基于访问者的语言环境)。 FreeMarker通过Template.createProcessingEnvironment (参见JavaDoc)支持,但Spring MVC可能不支持。

此外, Date对象始终以UTC格式存储日期时间。 您无需使用-D为其设置时区。

不,那看起来不错。 我建议您不要依赖user.timezone进行字符串格式化,因为最终有人会使用错误的时区启动您的webapp; 相反,你可以使用

DateFormat formatter = new SimpleDateFormat("hh:mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

顺便说一下,你见过CodeReview吗? 这个问题同样适用于这两个网站,因为这样你就可以用它来表达。

您可以像这样覆盖FreeMarkerView

public static class YourFreemarkerView extends FreeMarkerView {
    @Override
    protected void processTemplate(Template template, SimpleHash model, HttpServletResponse response)
            throws IOException, TemplateException {

        HttpRequestHashModel httpRequestHashModel = (HttpRequestHashModel)model.get(FreemarkerServlet.KEY_REQUEST);

        Environment env = template.createProcessingEnvironment(model, response.getWriter(), null);
        env.setLocale(RequestContextUtils.getLocale(httpRequestHashModel.getRequest()));
        env.setTimeZone(RequestContextUtils.getTimeZone(httpRequestHashModel.getRequest()));
        env.process();

    }       
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM