LocalDateTimeシーケンス化からグローバル一貫性シーケンス化を検討する
日アーチの一卒は尽きず、功は唐に寄付しないで海に入った.
くさび
前の2週間にSpringSecurityと1編の文章募集.を3編出しましたが、今週は簡単で使いやすい文章を書いて、頭を変えて、休みたいと思っています.
今日書くのはこの文章です:
このタイトルは人の話に似ていないように見えますが、とても公式な感じがします.まず、私たちのテーマは何ですか.
私たちのプロジェクトには一般的に2つのシーケンス化があります.
1つは
もう一つは私たちのプロジェクト内のシーケンス化です.自分で定義したJsonUtilでも、あなたが導入したサードパーティJSON処理ツール(例えば
この2つが異なると、シーケンス化されたデータに結果が異なる場合があるので、それを防ぐために、今日はプロジェクトのシーケンス化について検討します.
1.例を挙げる
まず例を挙げて、シーケンス化が一致しなければどのような効果が現れるかを見てみましょう.
これは一般的なアクセスインタフェースで、次の結果が返されます.
ここではtimestampのシーケンス化結果に注意する必要があります.timestampは
しかし、ここでのシーケンス化が他のスキームを使用している場合、このシーケンス化の結果は異なる体験になるかもしれません.私のプロジェクトでも
シーケンス化ツールクラス長は、上記と同様に
実際のプロジェクトでサードパーティインタフェースをHTTPドッキングするには一般的に必要であり、その中で転送されたデータは一般的に私たちのプロジェクトのJSONツールクラスのシーケンス化を経て文字列になってから転送され、シーケンス化スキームが異なるとシーケンス化中に転送される可能性のあるデータは私たちが望んでいない.
また、
ここで私がツールクラスでこの
したがって、プロジェクトにおけるシーケンス化と
2.実操案
プロジェクトにおけるシーケンス化の一貫性を保つ必要性について述べた(必要だと思うハハ).
では、この一致性をすれば、次のように言えます.
この変数に
グローバルに有効にするには、
では、
しかし、それだけではだめです.これは
このコードは、
コードの中の注釈のあれも1つのシーケンス化の変換をして、もしあなたのプロジェクトの中で比較的に長いLONGタイプの数字を使ったら、JSが完全な数字を手に入れられないかもしれません.javaの中のlongタイプはJSのnumberタイプより少し長いので、この時あなたはStringに変換してフロントに行かなければなりません.それは正しい数字を手に入れることができます.必要があれば、このセクションを開くことができます.
最後の一言は、builderから出てきた
後記
今日の
本文のコードは私も前の
本明細書のコード:コードクラウドアドレス GitHubアドレス
日アーチの一卒は尽きず、功は唐に寄付しないで海に入った.
あなた达のすべての点賛コレクションと評論はすべて私の知識に対して出力した莫大な肯定で、もし文の中に何か間違いや疑問点があれば、あるいは私の指導に対して評論区の下で伝言を残して、一緒に討論することができます.
私は耳で、ずっと知識の出力をしたい偽の文芸プログラマーです.
くさび
前の2週間にSpringSecurityと1編の文章募集.を3編出しましたが、今週は簡単で使いやすい文章を書いて、頭を変えて、休みたいと思っています.
今日書くのはこの文章です:
LocalDateTime
.このタイトルは人の話に似ていないように見えますが、とても公式な感じがします.まず、私たちのテーマは何ですか.
LocalDateTime
のシーケンス化を説明することで、プロジェクト全体のすべてのシーケンス化処理を引き出し、一致させます.私たちのプロジェクトには一般的に2つのシーケンス化があります.
1つは
SpringMVC
の公式のシーケンス化です.つまり、Spring
が作ってくれたシーケンス化です.例えば、インタフェースの上にResponseBody
の注釈を打って、SpringMVC
のメッセージ変換器がシーケンス化してくれます.もう一つは私たちのプロジェクト内のシーケンス化です.自分で定義したJsonUtilでも、あなたが導入したサードパーティJSON処理ツール(例えば
FastJson
)でも、私たちのプロジェクト内部のシーケンス化と言えるでしょう.この2つが異なると、シーケンス化されたデータに結果が異なる場合があるので、それを防ぐために、今日はプロジェクトのシーケンス化について検討します.
1.例を挙げる
まず例を挙げて、シーケンス化が一致しなければどのような効果が現れるかを見てみましょう.
@GetMapping("/api/anon")
public ApiResult test01() {
return ApiResult.ok(" ");
}
これは一般的なアクセスインタフェースで、次の結果が返されます.
{
"code": 200,
"msg": " ",
"data": {
" ": " "
},
"timestamp": "2020-07-19T23:07:07.738",
"fail": false,
"success": true
}
ここではtimestampのシーケンス化結果に注意する必要があります.timestampは
LocalDateTime
タイプで、SpringMVC
のメッセージ変換器がLocalDateTime
をシーケンス化する際に特別な処理はなく、LocalDateTime
のtoString()メソッドを直接呼び出したので、このシーケンス化結果の中にT
があります.しかし、ここでのシーケンス化が他のスキームを使用している場合、このシーケンス化の結果は異なる体験になるかもしれません.私のプロジェクトでも
Jackson
を採用してシーケンス化しています(Spring
でも使用されています).私たちが定義したJsonUtilがLocalDateTime
をシーケンス化するとどのような結果になるかを見ることができます.@Slf4j
public class JacksonUtil {
public static ObjectMapper objectMapper = new ObjectMapper();
/**
* Java JSON
*
* @param object
* @return
*/
public static String toJsonString(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
log.error("The JacksonUtil toJsonString is error :
", e);
throw new RuntimeException();
}
}
}
シーケンス化ツールクラス長は、上記と同様に
ApiResult
をシーケンス化して、どのような結果になるかを見てみましょう.{
"code": 400,
"msg": " ",
"timestamp": {
"month": "JULY",
"year": 2020,
"dayOfMonth": 19,
"hour": 23,
"minute": 25,
"monthValue": 7,
"nano": 596000000,
"second": 2,
"dayOfYear": 201,
"dayOfWeek": "SUNDAY",
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
"fail": true,
"success": false
}
Jackson
のデフォルトのObjectMapper
でシーケンス化された結果はこの鬼の姿で、シーケンス化が最後に文字列に変換されたので、このようなデータの先端を手に入れたら正常に時間タイプに変換できないに違いありません.LocalDateTime
はただの縮図で、文字列に対しても、異なるシーケンス化構成には異なる影響があり、文字列の中にはエスケープ文字があり、引用符があり、異なるスキームの結果が異なる可能性があります.実際のプロジェクトでサードパーティインタフェースをHTTPドッキングするには一般的に必要であり、その中で転送されたデータは一般的に私たちのプロジェクトのJSONツールクラスのシーケンス化を経て文字列になってから転送され、シーケンス化スキームが異なるとシーケンス化中に転送される可能性のあるデータは私たちが望んでいない.
また、
HttpServeletResponse
に直接データを書くインタフェースもあります.この場合、JSONデータを書くのが一般的です.例えば、public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setHeader("Cache-Control", "no-cache");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().println(JacksonUtil.toJsonString(ApiResult.fail(authException.getMessage())));
response.getWriter().flush();
}
ここで私がツールクラスでこの
ApiResult
を直接シーケンス化すると、フロントに渡されたデータも上記の例のような状況になります.LocalDateTime
シーケンス化の結果は私たちが望んでいるものではありません.したがって、プロジェクトにおけるシーケンス化と
Spring
におけるシーケンス化とが一致する必要がある.2.実操案
プロジェクトにおけるシーケンス化の一貫性を保つ必要性について述べた(必要だと思うハハ).
では、この一致性をすれば、次のように言えます.
Spring
のシーケンス化で戻ってきたオブジェクトのLocalDateTime
タイプの変数をシーケンス化したい場合は、簡単です.public class ApiResult implements Serializable {
private static final Map map = new HashMap<>(1);
private int code;
private String msg;
private Object data;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime timestamp;
この変数に
JsonFormat
注釈を付けるのは簡単ですが、これはグローバルではなく、どの変数にどの変数を加えるかが有効になります.グローバルに有効にするには、
Spring
の構成でSpring
で使用されているObjectMapper
を修正する必要があります.Jacksonを知っている仲間は知っているはずです.シーケンス化された様々な構成はこのObjectMapper
に配置されています.知らなくても大丈夫です.あなたは今知っています.では、
Spring
のObjectMapper
を構成することで、グローバルに有効にすることができます.@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
builder.locale(Locale.CHINA);
builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
builder.modules(javaTimeModule);
};
}
}
Jackson2ObjectMapperBuilderCustomizer
にシーケンス化スキームを追加することで、上記のコードはこれらの操作を行い、その後、最初のインタフェースに再びアクセスすると、次のような効果が得られます.{
"code": 200,
"msg": " ",
"data": {
" ": " "
},
"timestamp": "2020-07-20 00:06:12",
"fail": false,
"success": true
}
timestamp
の間にそのTは存在しません.私たちはLocalDateTime
のシーケンス化案に参加したからです.しかし、それだけではだめです.これは
LocalDateTime
のグローバルシーケンス化にすぎません.私たちは自分のツールクラスもSpring
と一致させる必要があります. @Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
{
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// mapper ,
// Include.Include.ALWAYS
// Include.NON_DEFAULT
// Include.NON_EMPTY ("") NULL , json
// Include.NON_NULL NULL
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
//
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
/**
* Long,BigInteger , String
*/
// SimpleModule simpleModule = new SimpleModule();
//
// simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
// simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
// simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
//
// objectMapper.registerModule(simpleModule);
// objectMapper Spring objectMapper
JacksonUtil.objectMapper = objectMapper;
return objectMapper;
}
このコードは、
Jackson2ObjectMapperBuilder
builderから出てきたObjectMapper
について、前のステップに進み、自分の望む属性を設定します.コードの中の注釈のあれも1つのシーケンス化の変換をして、もしあなたのプロジェクトの中で比較的に長いLONGタイプの数字を使ったら、JSが完全な数字を手に入れられないかもしれません.javaの中のlongタイプはJSのnumberタイプより少し長いので、この時あなたはStringに変換してフロントに行かなければなりません.それは正しい数字を手に入れることができます.必要があれば、このセクションを開くことができます.
最後の一言は、builderから出てきた
ObjectMapper
をツールクラスのObjectMapper
に割り当てることです.そうすると、2人は実際に1つのアドレスを指しています.つまり、同じオブジェクトを使用してシーケンス化されています.結果はもちろん同じです.後記
今日の
LocalDateTime
はここに着いて、みんなに役に立つことを望みます.本文のコードは私も前の
SpringSecruity
のdemoの中に置いて、みんなは直接中に行ってクラス名を検索することができます.本明細書のコード:コードクラウドアドレス GitHubアドレス
日アーチの一卒は尽きず、功は唐に寄付しないで海に入った.
あなた达のすべての点賛コレクションと評論はすべて私の知識に対して出力した莫大な肯定で、もし文の中に何か間違いや疑問点があれば、あるいは私の指導に対して評論区の下で伝言を残して、一緒に討論することができます.
私は耳で、ずっと知識の出力をしたい偽の文芸プログラマーです.