① 如何讓Jackson jsON生成的數據包含的中文以unicode方式編碼
Jackson JSON其實在默認設置下已經具備了對Unicode編碼的JSON數據進行解析。所欠缺的就是在序列化對象時缺少相應的步驟。好在Jackson JSON框架允許我們自定義序列化方法。那麼我們就來寫一個序列化類: 復制代碼代碼如下: import java.io.IOExce...
② 你常用的Java工具庫都有哪些
JavaSDK肯定是使用最廣的庫,所以本文的名單焦點是流行的第三方庫。該列表可能並不完善,所以如果你覺得有什麼應該出現在列表中的,請留下您的評論。非常感謝!
1、核心庫
Apache Commons Lang:來自Apache的核心庫,為java.lang API補充了許多常用的工具類,如字元串操作、對象的創建等。
Google Guava:來自谷歌的核心庫,包括集合(Collection)、緩存(Caching)、支持原語(Primitives)等。(示例)
2、HTML、XML Parser
Jsoup:一個簡化了的 HTML操作的庫。(示例)
STaX:一組可以高效處理XML的API。 (示例)
3、Web框架
Spring:Java平台上眾所周知的開源框架和依賴注入容器。(示例)
Struts2:來自Apache的流行Web框架。 (示例)
GoogleWebToolkit:Google提供的開發工具庫,主要用於構建和優化復雜的Web程序用。 (示例)
Strips:使用最新Java技術構建的Web程序框架,推薦使用。
Tapestry:面向組件的框架,用於使用Java創建動態、健壯、擴展性高的Web應用程序。
請猛擊這里查看以上面框架之間的比較。
4、圖表、報表、圖像
JFreeChart:用於創建如條形圖、折線圖、餅圖等圖表。
JFreeReport:創建於輸出PDF格式的報表。
JGraphT:創建圖像,其中只包含由線段連接的點集。
5、窗口
Swing:SDK提供的GUI庫。(示例)
SWT:eclipse提供的GUI庫。
SWT與Swing的比較。
6.、GUI框架
EclipseRCP。(示例)
7、自然語言處理
OpenNLP:來自Apache的自然語言處理庫。 (示例)
StanfordParser:斯坦福大學提供的自然語言處理庫。(示例)
如果你是一名NLP專家,請猛擊這里查看更多工具庫介紹。
8、靜態分析
EclipseJDT:由IBM提供的靜態分析庫,可以操作Java源代碼。(示例)
WALA:可以處理jar包文件(即位元組碼)的工具庫。(示例)
9、JSON
Jackson: 用於處理JSON數據格式的多用途的Java庫。Jackson 旨在快速、准確、輕量、對開人員友好之間找到最好的平衡點。
XStream:一個簡單用於對象和XML互相轉換的庫。
GoogleGson:一個專門用於Java對象和Json對象相互轉換的工具庫。(示例)
JSON-lib:用於beans、maps、collections、javaarrays、XML和JSON之間相互轉換操作的工具庫。
10、數學
ApacheCommonsMath:提供數學計算和數值統計需函數的工具庫。
11、日誌
ApacheLog4j:風行一時的日誌記錄操作庫。(示例)
Logback:當前流行的log4j項目的繼任者。
SLF4J(TheSimpleLoggingFacadeforJava): 各種日誌框架的一個簡單的外觀或抽象(如java.util.logging 、logback、log4j等),允許用戶在部署時加入需要的日誌框架。
12、Office
ApachePOI:利用其提供的APIs,可以使用純Java代碼操作各種基於微軟OLE2合成文檔格式的文檔。
Docx4j:一個用於創建、操作微軟公開的XML文件的庫(支持Worddocx、 Powerpointpptx和Excelxlsx)。
13、日期和時間
Joda-Time:如有質量問題包退包換的Java日期和時間類。
14、資料庫
Hibernate、EclipseLink、JPA
JDO
jOOQ
SpringJDBC、SpringData
ApacheDbUtils
15、開發工具
Lambok: 旨在減少代碼編寫的Java開發庫。
③ redis客戶端選型-Jedis、lettuce、Redisson
1.背景
研發部門對於客戶端選型比較廣泛和隨意,依賴的分支也不統一,感覺就像網路到一個就直接用,或者是有一個功能滿足就換,沒有考慮到其他組的使用情況以及集中維護。
另外一個是如果作為公司pom腳手架的基本組成部分,需要考慮統一成一個還是多個並存的問題,現在有兩個考量:如果性能不是大問題,建議統一集中為一個就行; 如果需要多個並存,至少不能多於2個客戶端。
2.比較
官方推薦的java客戶端只有Jedis、lettuce、Redisson,所以這次分析只針對這三個進行。
2.1.概述
Jedis: redis的Java實現客戶端,提供了比較全面的Redis命令的支持。
lettuce: Lettuce is a scalable thread-safe Redis client for synchronous, asynchronous and reactive usage. Multiple threads may share one connection if they avoid blocking and transactional operations such as BLPOP and MULTI/EXEC. Lettuce is built with netty. Supports advanced Redis features such as Sentinel, Cluster, Pipelining, Auto-Reconnect and Redis data models.
Redisson: Redisson是一個在Redis的基礎上實現的Java駐內存數據網格(In-Memory Data Grid)。它不僅提供了一系列的分布式的Java常用對象,還提供了許多分布式服務。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheler service) Redisson提供了使用Redis的最簡單和最便捷的方法。Redisson的宗旨是促進使用者對Redis的關注分離(Separation of Concern),從而讓使用者能夠將精力更集中地放在處理業務答舉邏輯上。
lettuce: 直接看官網的: https://lettuce.io/
2.2.性能
Jedis的性能比lettuce和Redisson都要差一點,三者的主要差異在於以下:
1.Jedis使用同步和阻塞IO的方式,不支持非同步;lettuce和Redisson支持非同步,底層是基於netty框架的事件驅動作為通信層。
2.Jedis設計上就是基於線程不安全來設計,一個連接只能被一個線程使用,但清皮碧是可以結合連接池來提高其性能;lettuce和Redis基於線程安全來設計的,一個連接是被共享使用的,但是也提供了連接池,主要用於事務以及阻塞操作的命令。
3.lettuce和Redisson支持非同步流的方式。
一些公開的benchmark結果:
Redisson和Jedis:
https://dzone.com/articles/redisson-pro-vs-jedis-which-is-faster
Jedis和lettuce:
https://www.bby.cn/detail.html?id=9108
上面的測試結果都是比較久遠的,沒找到三者共同參與的性能測試結果。
沒有做三者的性能基準測試,主要是無目的性、無針對性的條件限制(並發數、數據量、指令kv的握燃大小范圍),很難去做定量和可對比的基準測試(主要是我懶)。
2.3.功能
Jedis: 提供比較全面的redis原生指令的支持,上層封裝比較弱,集群特性支持度非常低,高級特性幾乎沒有。
lettuce: 高級redis客戶端,支持各種模式的redis連接和操作,高級特性幾乎沒有。
Redisson: 高級redis客戶端,支持各種模式的redis連接和操作,同時提供一大堆的實用功能。
Jedis和lettuce沒什麼功能,就簡單的操作,連分布式鎖都需要自己實現,所以先聊聊Redisson的高級功能,中間偶爾會用Jedis和lettuce做對比。
1.十幾種編碼方式。
Redisson是基於對象的操作,對於key對象和value對象可用不同的高級編碼方式:
JsonJacksonCodec、AvroJacksonCodec、SmileJacksonCodec、CborJacksonCodec、MsgPackJacksonCodec、IonJacksonCodec、KryoCodec、SerializationCodec、FstCodec、LZ4Codec、SnappyCodec、CompositeCodec
和四種基本的編碼方式:
JsonJacksonMapCodec、StringCodec、LongCodec、ByteArrayCodec
而Jedis操作只針對位元組數組, lettuce支持ByteArrayCodec、StringCodec、CipherCodec、CompressionCodec四種。
按需使用,沒有編碼方式的比對。
2.分布式集合。
把大集合拆分並均勻分布到各個節點上,集合包括Set、Map、BitSet、Bloom Filter、Spring Cache和Hibernate Cache,並且支持本地緩存。(只有專業版才能用)分布式鎖。
各種各樣的分布式鎖: 可重入鎖ReentrantLock、公平鎖FairLock、聯鎖MultiLock、紅鎖RedLock、讀寫鎖ReadWriteLock、信號量Semaphore、可過期的信號量PermitExpirableSemaphore、計數器CountDownLatch
3.RPC
4.分布式調度任務服務
5.分布式MR
6.復雜多維對象結構和對象引用的支持
7.集群pipeline
lettuce也支持。
jedis不支持,jedis連多key(分布在不同節點的)操作都不支持。
8.事務
提供了XA Transactions標準的實現,可以集成到Spring中。(只有專業版才能用)
9.集群管理工具
(只有專業版才能用)
10.限流器
分布式的限流工具(有timeout功能)。
11.自增/分布式ID
12.BloomFilter
13.延遲隊列
2.4.選型
Spring最早是默認以Jedis作為客戶端, 但是後來改為了lettuce, lettuce與Jedis相比比較明顯的特點是非同步和線程安全, 底層是netty大殺器作為通信層, 性能比Jedis的線程不安全+連接池要好。
Redisson是以其強大的功能以及面向對象的設計優於其他兩者。
根據我們的業務需要:
1.限流
2.分布式鎖
3.緩存
4.GID生成
5.延時隊列
6.lua腳本
7.請求合並
Redisson都能滿足,實際上單是使用Redisson作為Spring的客戶端就足夠了。
個人傾向lettuce + Redisson。
④ springmvc怎麼返回json
SpringMVC返回數據有三種方式
1、第一種方式是spring2時代的產物,也就是每個json視圖controller配置一個Jsoniew。如:<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/> 或者<bean id="defaultJsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>同樣要用jackson的jar包。
2、第二種使用JSON工具將對象序列化成json,常用工具Jackson,fastjson,gson。
利用HttpServletResponse,然後獲取response.getOutputStream()或response.getWriter()
直接輸出。
示例:
[java] view plain print?
public class JsonUtil
{
private static Gson gson=new Gson();
/**
* @MethodName : toJson
* @Description : 將對象轉為JSON串,此方法能夠滿足大部分需求
* @param src
* :將要被轉化的對象
* @return :轉化後的JSON串
*/
public static String toJson(Object src) {
if (src == null) {
return gson.toJson(JsonNull.INSTANCE);
}
return gson.toJson(src);
}
}
3、第三種利用spring mvc3的註解@ResponseBody
例如:
[java] view plain print?
@ResponseBody
@RequestMapping("/list")
public List<String> list(ModelMap modelMap) {
String hql = "select c from Clothing c ";
Page<Clothing> page = new Page<Clothing>();
page.setPageSize(6);
page = clothingServiceImpl.queryForPageByHql(page, hql);
return page.getResult();
}
然後使用spring mvc的默認配置就可以返回json了,不過需要jackson的jar包
⑤ java後台如何生成.json文件
如果用SpringMvc的話配置一下就可以了,默認返回json:
<bean
class="org.springframework.web.servlet.view.">
<property name="mediaTypes">
<map>
<entry key="html" value="text/html" />
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/pages/" />
<property name="suffix" value=".jsp" />
<property name="order" value="0" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
⑥ 如何讓Jackson JSON生成的數據包含的中文以unicode方式編碼
Jackson JSON其實在默認設置下已經具備了對Unicode編碼的JSON數據進行解析。所欠缺的就是在序列化對象時缺少相應的步驟。好在Jackson JSON框架允許我們自定義序列化方法。那麼我們就來寫一個序列化類:
復制代碼代碼如下:
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.impl.JsonWriteContext;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.util.CharTypes;
public class StringUnicodeSerializer extends JsonSerializer<String> {
private final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
private final int[] ESCAPE_CODES = CharTypes.get7BitOutputEscapes();
private void writeUnicodeEscape(JsonGenerator gen, char c) throws IOException {
gen.writeRaw('\\');
gen.writeRaw('u');
gen.writeRaw(HEX_CHARS[(c >> 12) & 0xF]);
gen.writeRaw(HEX_CHARS[(c >> 8) & 0xF]);
gen.writeRaw(HEX_CHARS[(c >> 4) & 0xF]);
gen.writeRaw(HEX_CHARS[c & 0xF]);
}
private void writeShortEscape(JsonGenerator gen, char c) throws IOException {
gen.writeRaw('\\');
gen.writeRaw(c);
}
@Override
public void serialize(String str, JsonGenerator gen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
int status = ((JsonWriteContext) gen.getOutputContext()).writeValue();
switch (status) {
case JsonWriteContext.STATUS_OK_AFTER_COLON:
gen.writeRaw(':');
break;
case JsonWriteContext.STATUS_OK_AFTER_COMMA:
gen.writeRaw(',');
break;
case JsonWriteContext.STATUS_EXPECT_NAME:
throw new JsonGenerationException("Can not write string value here");
}
gen.writeRaw('"');//寫入JSON中字元串的開頭引號
for (char c : str.toCharArray()) {
if (c >= 0x80){
writeUnicodeEscape(gen, c); // 為所有非ASCII字元生成轉義的unicode字元
}else {
// 為ASCII字元中前128個字元使用轉義的unicode字元
int code = (c < ESCAPE_CODES.length ? ESCAPE_CODES[c] : 0);
if (code == 0){
gen.writeRaw(c); // 此處不用轉義
}else if (code < 0){
writeUnicodeEscape(gen, (char) (-code - 1)); // 通用轉義字元
}else {
writeShortEscape(gen, (char) code); // 短轉義字元 (\n \t ...)
}
}
}
gen.writeRaw('"');//寫入JSON中字元串的結束引號
}
}
這個序列化類將要對應用中所有使用Jackson JSON的地方全都用一種方法來處理字元串類型。光有了方法還不行,還要對它進行注冊。讓Jackson JSON在序列化對象的時候使用剛剛定義好的方法:
復制代碼代碼如下:
if (objectMapper== null){
objectMapper= new ObjectMapper();
//當找不到對應的序列化器時 忽略此欄位
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
//使Jackson JSON支持Unicode編碼非ASCII字元
CustomSerializerFactory serializerFactory= new CustomSerializerFactory();
serializerFactory.addSpecificMapping(String.class, new StringUnicodeSerializer());
objectMapper.setSerializerFactory(serializerFactory);
//支持結束
}
接下來我們來做一個測試用的對象,驗證我們的代碼:
復制代碼代碼如下:
import java.util.Date;
import net.csdn.blog.chaijunkun.util.DateDeserializer;
import net.csdn.blog.chaijunkun.util.DateSerializer;
import net.csdn.blog.chaijunkun.util.DateTimeDeserializer;
import net.csdn.blog.chaijunkun.util.DateTimeSerializer;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
@JsonPropertyOrder(alphabetic= false)
public class DemoObj {
private Integer sid;
private String stuName;
private Boolean sex;
@JsonSerialize(using= DateSerializer.class)
@JsonDeserialize(using= DateDeserializer.class)
private Date birthday;
@JsonSerialize(using= DateTimeSerializer.class)
@JsonDeserialize(using= DateTimeDeserializer.class)
private Date logTime;
//Getters and Setters
}
從代碼上可以看出,我們並沒有對String類型的屬性強制指定用何種序列與反序列方法。然後我們來構造測試用例:
復制代碼代碼如下:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import net.csdn.blog.chaijunkun.json.DemoObj;
import net.csdn.blog.chaijunkun.util.JSONUtil;
import org.apache.log4j.Logger;
public class JSONTest {
private static Logger logger= Logger.getLogger(JSONTest.class);
private static String json= "{\"sid\":2,\"stuName\":\"\u6C5F\u5357Style\",\"sex\":true,\"birthday\":\"2012-07-15\",\"logTime\":\"2012-12-04 19:22:36\"}";
public static void main(String[] args) {
DemoObj objSrc= new DemoObj();
objSrc.setSid(1);
objSrc.setStuName("鳥叔");
objSrc.setSex(true);
Calendar calendar= Calendar.getInstance();
calendar.set(1977, Calendar.DECEMBER, 31, 0, 0, 0);
objSrc.setBirthday(calendar.getTime());
objSrc.setLogTime(new Date());
logger.info(String.format("轉換為JSON後的數據:%s", JSONUtil.toJSON(objSrc)));
DemoObj objDes= JSONUtil.fromJSON(json, DemoObj.class);
if(objDes==null){
logger.info("反序列化失敗");
}else{
logger.info("反序列化成功");
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
logger.info(String.format("標識:%d", objDes.getSid()));
logger.info(String.format("姓名:%s", objDes.getStuName()));
logger.info(String.format("性別:%s", objDes.getSex()==true?"男":"女"));
logger.info(String.format("生日:%s", sdf.format(objDes.getBirthday())));
logger.info(String.format("登錄日期:%s", sdf.format(objDes.getLogTime())));
}
}
}
看一下輸出:
復制代碼代碼如下:
轉換為JSON後的數據:{"sid":1,"stuName":"\u9E1F\u53D4","sex":true,"birthday":"1977-12-31","logTime":"2012-12-04 19:31:57"}
反序列化成功
標識:2
姓名:江南Style
性別:男
生日:2012-07-15 00:00:00
登錄日期:2012-12-04 19:22:36
我們看到,已經成功將中文字元顯示成為了Unicode編碼的數據。同樣,我們之前構造的Unicode編碼的數據,在不經過任何修改的情況下成功顯示出來了。
細心的朋友也許觀察到了,在測試用的對象定義代碼中,針對同樣Date類型的屬性「birthday」和「logTime」,我們指定了不同的序列化與反序列化方法。讓我們來看爛這兩個有什麼不同:
復制代碼代碼如下:
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class DateTimeSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate= sdf.format(date);
gen.writeString(formattedDate);
}
}
復制代碼代碼如下:
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
public class DateTimeDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
String dateFormat= "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf= new SimpleDateFormat(dateFormat);
try{
String fieldData= parser.getText();
return sdf.parse(fieldData);
}catch (Exception e) {
Calendar ca= Calendar.getInstance();
ca.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
return ca.getTime();
}
}
}
復制代碼代碼如下:
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class DateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
String formattedDate= sdf.format(date);
gen.writeString(formattedDate);
}
}
復制代碼代碼如下:
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
public class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
String dateFormat= "yyyy-MM-dd";
SimpleDateFormat sdf= new SimpleDateFormat(dateFormat);
try{
String fieldData= parser.getText();
return sdf.parse(fieldData);
}catch (Exception e) {
Calendar ca= Calendar.getInstance();
ca.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
return ca.getTime();
}
}
}
⑦ 如何讓Jackson JSON生成的數據包含的中文以unicode方式編碼
需要在序列化與反序列化對象的時候對數據進行修改,當發現數據源值為空時需要讓生成的版JSON顯示改欄位權為「遊客」。
可是我無論如何指定序列化器與反序列化器都無效。程序根本走不到指定的代碼中去。後來我得出結論,Jackson JSON在反序列化對象的時候,若JSON數據中對應屬性為null,則不會走自定義的反序列化器;
同樣地,當你設置對象的某個屬性值為null時,在將其序列化成JSON時,也不會走自定義的序列化器。因此若有類似的需求,請在序列化與反序列化之前通過硬代碼形式判斷和修改,千萬不要什麼事都指望著序列化器與反序列化器。