Analysis of the time difference of 8 hours displayed on the front end of the Spring project

  During development, I sometimes heard colleagues from other projects say that the time difference between the front-end display is 8 hours, which is due to the time zone problem, because China happens to be GMT+8, which is 8 hours earlier than GMT. But the strange thing is, why haven't we encountered it in our project? So, I wrote a simple example to confirm that there is no problem with us, and consulted how colleagues in other project teams appeared, so I will record it here.

1. Write a simple demo to restore various scenarios

        Define Controller

@RequestMapping("/list")
public String showAll(ModelMap modelMap) {

	List<Article> articles = mapper.getArticlesByUserId(1);
	modelMap.addAttribute("articles", articles);
	return "main.ftl";
}

@RequestMapping("/list2")
public ModelAndView listall(HttpServletRequest request, HttpServletResponse response) {

	List<Article> articles = mapper.getArticlesByUserId(1);
	ModelAndView mav = new ModelAndView("list");
	mav.addObject("articles", articles);
	return mav;
}

@ResponseBody
@RequestMapping("/list3")
public Map<String, Object> listall3(HttpServletRequest request, HttpServletResponse response) {

	List<Article> articles = mapper.getArticlesByUserId(1);
	Map<String, Object> map = new HashMap<String, Object>();
	map.put("articles", articles);
	return map;
}

1./list is displayed through the freemark template, and the time is displayed as OK

<#list articles as article>
	<div>${article.id}. ${article.title}: ${article.content}: ${(article.updateTime)?string("yyyy-MM-dd HH:mm:ss")}</div>
</#list>

        Access requests, with no timing issues, are as follows:



2./list2 is displayed through jsp, and the time is also OK

list.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>article list</title>
</head>
<body>
	<c:forEach items="${articles}" var="item">  
        ${item.id }--${item.title }--${item.content}--${item.updateTime}<br />
	</c:forEach>
</body>
</html>

        Access requests, with no timing issues, are as follows:


 

3./list3 returns map directly, json string display


        The time field has become a long integer display, but the time is still correct. In the actual application of our project, the front-end JS is converted into a string and displayed.

        It turns out that other projects with problems are converted into strings by @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") on the time field in the background, and then displayed directly on the front end.

        So, I added @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") annotation to the updateTime field of Article.java, and requested the page again to display the following, updateTime is 8 hours later than the real time in the database :


        In the article " Using @RequestBody, @ResponseBody annotations in SpringMVC to realize automatic conversion of Java objects and XML/JSON data (below) ", we know that objects converted to JSON format provide front-end display, and this process is annotated by @RestController of Spring MVC Identify and use MappingJackson2HttpMessageConverter for message conversion, and we have jackson in our project, and Jackson uses GMT+0 when serializing the time type field (java.util.Date type format is a string), not " localized" time zone settings. Jackson FAQ: Date Handling: All time objects that have associated TimeZone (java.util.Calendar etc) that Jackson constructs use the standard timezone (GMT), not the local time zone (whatever that might be). That is: Jackson defaults to using GMT for all processing unless specifically told otherwise.

        According to the information, this problem can be solved by setting the default time zone of the host, as follows:


        However, by looking at the source code, the timezone set in the publicvoidconfigure(ObjectMapper objectMapper) method happens to be unassigned.

 

2. Solutions

1. Return the Date type directly and let the front-end js or jsp handle it

2. The tag <mvc:annotation-driven> in the configuration file of Spring MVC will instantiate various message conversion object instances by default. The key to solving the above problem is to replace the default JSON message converter with a custom time zone.

 

<mvc:annotation-driven></mvc:annotation-driven>

change into:

<mvc:annotation-driven>
	<mvc:message-converters>
	<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
		<property name="objectMapper">
				<bean class="com.fasterxml.jackson.databind.ObjectMapper">
					<property name="timeZone">
					<bean class="java.util.TimeZone" factory-method="getDefault" />
					</property>
				</bean>
		</property>
	</bean>
	</mvc:message-converters>
</mvc:annotation-driven>

        See attachment for example code. 

 

Reference article: https://blog.csdn.net/oShuSheng1/article/details/49614867

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc#mvc-config-message-converters

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326077149&siteId=291194637