Java如何对微信各种类型消息进行封装

这篇文章主要介绍Java如何对微信各种类型消息进行封装,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

成都创新互联公司服务项目包括拉萨网站建设、拉萨网站制作、拉萨网页制作以及拉萨网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,拉萨网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到拉萨省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

第一步:找到com.wtz.message.response包,新建类Image.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午8:38:37
 * version:1.0
 * description:图片的实体类
 */
public class Image {
 //图片媒体ID
 private String MediaId;
 
 public String getMediaId() {
 return MediaId;
 }
 public void setMediaId(String mediaId) {
 MediaId = mediaId;
 }
}

第二步:找到com.wtz.message.response包,新建类ImageMessage.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午8:49:57
 * version:1.0
 * description:图片消息类
 */
public class ImageMessage extends BaseMessage {
 //图片对象
 private Image image;

 public Image getImage() {
 return image;
 }

 public void setImage(Image image) {
 this.image = image;
 }
}

第三步:找到com.wtz.message.response包,新建类Video.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:02:14
 * version:1.0
 * description:视频的实体类
 */
public class Video {
 //视频消息的媒体ID
 private String MediaId;
 //视频消息的标题
 private String Title;
 //视频消息的描述
 private String Description;
 
 public String getMediaId() {
 return MediaId;
 }
 public void setMediaId(String mediaId) {
 MediaId = mediaId;
 }
 public String getTitle() {
 return Title;
 }
 public void setTitle(String title) {
 Title = title;
 }
 public String getDescription() {
 return Description;
 }
 public void setDescription(String description) {
 Description = description;
 }
}

第四步:找到com.wtz.message.response包,新建类VideoMessage.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:10:14
 * version:1.0
 * description:视频消息类
 */
public class VideoMessage extends BaseMessage{
 //视频对象
 private Video video;

 public Video getVideo() {
 return video;
 }

 public void setVideo(Video video) {
 this.video = video;
 }
}

第五步:找到com.wtz.message.response包,新建类Voice.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:21:47
 * version:1.0
 * description:语音消息实体类
 */
public class Voice {
 //语音媒体编号
 private String MediaId;
 
 public String getMediaId() {
 return MediaId;
 }
 public void setMediaId(String mediaId) {
 MediaId = mediaId;
 }
}

第六步:找到com.wtz.message.response包,新建类VoiceMessage.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:44:58
 * version:1.0

 * description:语音消息类  */ public class VoiceMessage extends BaseMessage{  //语音对象  private Voice voice;  public Voice getVoice() {  return voice;  }  public void setVoice(Voice voice) {  this.voice = voice;  } }

第七步:找到com.wtz.message.response包,新建类Music.java

package com.wtz.message.response;
/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:48:11
 * version:1.0
 * description:音乐消息实体类
 */
public class Music {
 //音乐标题
 private String Title;
 //音乐描述
 private String Description;
 //音乐链接
 private String MusicUrl;
 //高品质音乐链接
 private String HQMusicUrl;
 //缩略图的媒体ID
 private String ThumbMediaId;
 
 public String getTitle() {
 return Title;
 }
 public void setTitle(String title) {
 Title = title;
 }
 public String getDescription() {
 return Description;
 }
 public void setDescription(String description) {
 Description = description;
 }
 public String getMusicUrl() {
 return MusicUrl;
 }
 public void setMusicUrl(String musicUrl) {
 MusicUrl = musicUrl;
 }
 public String getHQMusicUrl() {
 return HQMusicUrl;
 }
 public void setHQMusicUrl(String hQMusicUrl) {
 HQMusicUrl = hQMusicUrl;
 }
 public String getThumbMediaId() {
 return ThumbMediaId;
 }
 public void setThumbMediaId(String thumbMediaId) {
 ThumbMediaId = thumbMediaId;
 }
}

第八步:找到com.wtz.message.response包,新建类MusicMessage.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午9:58:21
 * 

version:1.0

 * 

description:音乐消息类

 */ public class MusicMessage extends BaseMessage{  //音乐对象  private Music music;  public Music getMusic() {  return music;  }  public void setMusic(Music music) {  this.music = music;  } }

第九步:找到com.wtz.message.response包,新建类Article.java

package com.wtz.message.response;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午10:05:29
 * 

version:1.0

 * 

description:图文实体类

 */ public class Article {  //图文标题  private String Title;  //图文描述  private String Description;  //图片链接,支持JPG,PNG格式,较好的效果为大图  private String PicUrl;  //图文消息跳转链接  private String Url;    public String getTitle() {  return Title;  }  public void setTitle(String title) {  Title = title;  }  public String getDescription() {  return Description;  }  public void setDescription(String description) {  Description = description;  }  public String getPicUrl() {  return PicUrl;  }  public void setPicUrl(String picUrl) {  PicUrl = picUrl;  }  public String getUrl() {  return Url;  }  public void setUrl(String url) {  Url = url;  } }

第十步:找到com.wtz.message.response包,新建类NewsMessage.java

package com.wtz.message.response;

import java.util.List;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午10:16:22
 * 

version:1.0

 * 

description:图文消息类

 */ public class NewsMessage extends BaseMessage{  //图文条数  private int ArticleCount;  //多条图文消息信息,默认第一个item为大图  private List
 Articles;    public int getArticleCount() {  return ArticleCount;  }  public void setArticleCount(int articleCount) {  ArticleCount = articleCount;  }  public List
 getArticles() {  return Articles;  }  public void setArticles(List
 articles) {  Articles = articles;  } }

第十一步:新建包com.wtz.message.request,新建类BaseMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午10:53:23
 * 

version:1.0

 * 

description:请求消息基类(普通用户->公众账号)

 * 

站在服务器端的视角:接收信息

 */ public class BaseMessage {  //开发者微信号  private String ToUserName;  //发送方账号(一个OpenId)  private String FromUserName;  //消息创建时间(整型)  private long CreateTime;  //消息类型  private String MsgType;  //消息ID,64位整型  private long MsgId;    public String getToUserName() {  return ToUserName;  }  public void setToUserName(String toUserName) {  ToUserName = toUserName;  }  public String getFromUserName() {  return FromUserName;  }  public void setFromUserName(String fromUserName) {  FromUserName = fromUserName;  }  public long getCreateTime() {  return CreateTime;  }  public void setCreateTime(long createTime) {  CreateTime = createTime;  }  public String getMsgType() {  return MsgType;  }  public void setMsgType(String msgType) {  MsgType = msgType;  }  public long getMsgId() {  return MsgId;  }  public void setMsgId(long msgId) {  MsgId = msgId;  } }

第十二步:找到com.wtz.message.request包,新建类TextMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午11:04:35
 * 

version:1.0

 * 

description:文本消息

 */ public class TextMessage extends BaseMessage{  //消息内容  private String Content;  public String getContent() {  return Content;  }  public void setContent(String content) {  Content = content;  } }

第十三步:找到com.wtz.message.request包,新建类ImageMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午11:20:50
 * 

version:1.0

 * 

description:图片消息

 */ public class ImageMessage extends BaseMessage{  //图片链接  private String PicUrl;  //图片消息媒体ID  private String MediaId;    public String getPicUrl() {  return PicUrl;  }  public void setPicUrl(String picUrl) {  PicUrl = picUrl;  }  public String getMediaId() {  return MediaId;  }  public void setMediaId(String mediaId) {  MediaId = mediaId;  } }

第十四步:找到com.wtz.message.request包,新建类VoiceMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午11:27:40
 * 

version:1.0

 * 

description:语音消息类

 */ public class VoiceMessage extends BaseMessage {  //媒体ID  private String MediaId;  //语音格式  private String Format;  public String getMediaId() {  return MediaId;  }  public void setMediaId(String mediaId) {  MediaId = mediaId;  }  public String getFormat() {  return Format;  }  public void setFormat(String format) {  Format = format;  } }

第十五步:找到com.wtz.message.request包,新建类VideoMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:28:03
 * 

version:1.0

 * 

description:视频消息类

 */ public class VideoMessage extends BaseMessage {  //视频消息媒体ID  private String MediaId;  //视频消息缩略图的媒体ID  private String ThumbMediaId;    public String getMediaId() {  return MediaId;  }  public void setMediaId(String mediaId) {  MediaId = mediaId;  }  public String getThumbMediaId() {  return ThumbMediaId;  }  public void setThumbMediaId(String thumbMediaId) {  ThumbMediaId = thumbMediaId;  } }

第十六步:找到com.wtz.message.request包,新建类LocatonMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:27:40
 * 

version:1.0

 * 

description:地理位置消息类

 */ public class LocationMessage extends BaseMessage {  //地理位置纬度  private String Location_X;  //地理位置经度  private String Location_Y;  //地图缩放大小  private String Scale;  //地理位置信息  private String Label;    public String getLocation_X() {  return Location_X;  }  public void setLocation_X(String location_X) {  Location_X = location_X;  }  public String getLocation_Y() {  return Location_Y;  }  public void setLocation_Y(String location_Y) {  Location_Y = location_Y;  }  public String getScale() {  return Scale;  }  public void setScale(String scale) {  Scale = scale;  }  public String getLabel() {  return Label;  }  public void setLabel(String label) {  Label = label;  } }

第十七步:找到com.wtz.message.request包,新建类LinkMessage.java

package com.wtz.message.request;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午1:58:04
 * 

version:1.0

 * 

description:链接消息类

 */ public class LinkMessage extends BaseMessage {  //消息标题  private String Title;  //消息描述  private String Description;  //消息链接  private String Url;    public String getTitle() {  return Title;  }  public void setTitle(String title) {  Title = title;  }  public String getDescription() {  return Description;  }  public void setDescription(String description) {  Description = description;  }  public String getUrl() {  return Url;  }  public void setUrl(String url) {  Url = url;  } }

第十八步:新建包com.wtz.message.event,新建类BaseEventMessage.java

package com.wtz.message.event;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 上午10:44:09
 * 

version:1.0

 * 

description:基础事件消息类

 */ public class BaseEventMessage {  //开发者微信号  private String ToUserName;  //发送方账号(一个OpenID)  private String FromUserName;  //消息创建时间(整型)  private long CreateTime;  //消息类型  private String MsgType;  //事件类型  private String Event;    public String getToUserName() {  return ToUserName;  }  public void setToUserName(String toUserName) {  ToUserName = toUserName;  }  public String getFromUserName() {  return FromUserName;  }  public void setFromUserName(String fromUserName) {  FromUserName = fromUserName;  }  public long getCreateTime() {  return CreateTime;  }  public void setCreateTime(long createTime) {  CreateTime = createTime;  }  public String getMsgType() {  return MsgType;  }  public void setMsgType(String msgType) {  MsgType = msgType;  }  public String getEvent() {  return Event;  }  public void setEvent(String event) {  Event = event;  } }

第十九步:找到包com.wtz.message.event,新建类QRCodeEventMessage.java

package com.wtz.message.event;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:24:30
 * 

version:1.0

 * 

description:扫描带参数二维码事件类

 */ public class QRCodeEventMessage extends BaseEventMessage{  //事件Key值  private String EventKey;  //用于换取二维码图片  private String Ticket;    public String getEventKey() {  return EventKey;  }  public void setEventKey(String eventKey) {  EventKey = eventKey;  }  public String getTicket() {  return Ticket;  }  public void setTicket(String ticket) {  Ticket = ticket;  }  }

第二十步:找到包com.wtz.message.event,新建类SubscribeEventMessage.java

package com.wtz.message.event;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:27:11
 * 

version:1.0

 * 

description:关注/取消关注事件类

 */ public class SubscribeEventMessage extends BaseEventMessage{   }

第二十一步:找到包com.wtz.message.event,新建类MenuEventMessage.java

package com.wtz.message.event;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:32:42
 * 

version:1.0

 * 

description:自定义菜单事件类

 */ public class MenuEventMessage extends BaseEventMessage{  //事件Key值,与自定义菜单接口中Key值对应  private String EventKey;  public String getEventKey() {  return EventKey;  }  public void setEventKey(String eventKey) {  EventKey = eventKey;  } }

第二十二步:找到包com.wtz.message.event,新建类LocationEventMessage.java

package com.wtz.message.event;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月20日 下午3:37:50
 * 

version:1.0

 * 

description:上报地理位置事件类

 */ public class LocationEventMessage extends BaseEventMessage{  //地理位置纬度  private String Latitude;  //地理位置经度  private String Longitude;  //地理位置精度  private String Precision;    public String getLatitude() {  return Latitude;  }  public void setLatitude(String latitude) {  Latitude = latitude;  }  public String getLongitude() {  return Longitude;  }  public void setLongitude(String longitude) {  Longitude = longitude;  }  public String getPrecision() {  return Precision;  }  public void setPrecision(String precision) {  Precision = precision;  } }

第二十三步:找到包com.wtz.util下的MessageUtil.java类,修改这个类添加请求和回复的各种消息类型,事件类型,添加将各种类型消息转换成XML格式的方法

package com.wtz.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.wtz.message.response.ImageMessage;
import com.wtz.message.response.MusicMessage;
import com.wtz.message.response.NewsMessage;
import com.wtz.message.response.TextMessage;
import com.wtz.message.response.VideoMessage;
import com.wtz.message.response.VoiceMessage;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月19日 下午3:29:58
 * 

version:1.0

 * 

description:消息处理工具类

 */ public class MessageUtil {  //请求消息类型:文本  public static final String REQ_MESSAGE_TYPE_TEXT = "text";  //请求消息类型:图片  public static final String REQ_MESSAGE_TYPE_IMAGE = "image";  //请求消息类型:语音  public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  //请求消息类型:视频  public static final String REQ_MESSAGE_TYPE_VIDEO = "video";  //请求消息类型:地理位置  public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  //请求消息类型:链接  public static final String REQ_MESSAGE_TYPE_LINK = "link";  //请求消息类型:事件推送  public static final String REQ_MESSAGE_TYPE_EVENT = "event";    //---------------------------------------------------------------    //事件类型:subscribe(订阅)  public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  //事件类型:unsubscribe(取消订阅)  public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  //事件类型:scan(用户已关注时的扫描带参数的二维码)  public static final String EVENT_TYPE_SCAN = "scan";  //事件类型:LOCATION(上报地理位置)  public static final String EVENT_TYPE_LOCATION = "LOCATION";  //事件类型:CLICK(自定义菜单)  public static final String EVENT_TYPE_CLICK = "CLICK";    //---------------------------------------------------------------    //响应消息类型:文本  public static final String RESP_MESSAGE_TYPE_TEXT = "text";  //响应详细类型:图片  public static final String RESP_MESSAGE_TYPE_IMAGE = "image";  //响应消息类型:语音  public static final String RESP_MESSAGE_TYPE_VOICE = "voice";  //响应消息类型:视频  public static final String RESP_MESSAGE_TYPE_VIDEO = "video";  //响应详细类型:音乐  public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  //响应消息类型:图文  public static final String RESP_MESSAGE_TYPE_NEWS = "news";    //---------------------------------------------------------------    //从流中解析出每个节点的内容  public static Map parseXml(HttpServletRequest request) throws IOException{  Map map = new HashMap();    //从输入流中获取流对象  InputStream in = request.getInputStream();    //构建SAX阅读器对象  SAXReader reader = new SAXReader();  try {   //从流中获得文档对象   Document doc = reader.read(in);      //获得根节点   Element root = doc.getRootElement();      //获取根节点下的所有子节点   List children = root.elements();      for(Element e:children){   //遍历每一个节点,并按照节点名--节点值放入map中   map.put(e.getName(), e.getText());   System.out.println("用户发送的消息XML解析为:" + e.getName() + e.getText());   }      //关闭流   in.close();   in = null;  } catch (DocumentException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }    return map;  }    /**  * 用于扩展节点数据按照,中间加了CDATA段  */  private static XStream xstream = new XStream(new XppDriver(){  public HierarchicalStreamWriter createWriter(Writer out){   return new PrettyPrintWriter(out){   boolean cdata = true;   public void startNode(String name,Class clazz){    super.startNode(name,clazz);   }      protected void writeText(QuickWriter writer,String text){    if(cdata){    writer.write("");    }else{    writer.write(text);    }   }   };  }  });    /**  * 将文本消息对象转换成XML格式  * params:textMessage 文本消息对象  * return:xml  */  public static String messageToXml(TextMessage textMessage){  xstream.alias("xml",textMessage.getClass());  return xstream.toXML(textMessage);  }    /**  * 将图片消息对象转换成XML格式  * params:imageMessage  * return:xml  */  public static String messageToXml(ImageMessage imageMessage){  xstream.alias("xml", imageMessage.getClass());  return xstream.toXML(imageMessage);  }    /**  * 将语音消息对象转换成XML格式  * params:voiceMessage  * return:xml  */  public static String messageToXml(VoiceMessage voiceMessage){  xstream.alias("xml",voiceMessage.getClass());  return xstream.toXML(voiceMessage);  }    /**  * 将视频消息对象转换成XML格式  * params:videoMessage  * return:xml  */  public static String messageToXml(VideoMessage videoMessage){  xstream.alias("xml",videoMessage.getClass());  return xstream.toXML(videoMessage);  }    /**  * 将音乐消息对象转换成XML格式  * params:musicMessage  * return:xml  */  public static String messageToXml(MusicMessage musicMessage){  xstream.alias("xml",musicMessage.getClass());  return xstream.toXML(musicMessage);  }    /**  * 将图文消息对象转换成XML格式  * params:newsMessage  * return:xml  */  public static String messageToXml(NewsMessage newsMessage){  xstream.alias("xml",newsMessage.getClass());  return xstream.toXML(newsMessage);  } }

第二十四步:找到包com.wtz.util下的ProcessService.java类,修改dealRequest方法响应各种类型的消息

package com.wtz.util;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.wtz.message.response.TextMessage;

/**
 * @author wangtianze QQ:864620012
 * @date 2017年4月19日 下午8:04:14
 * 

version:1.0

 * 

description:核心服务类

 */ public class ProcessService {  public static String dealRequest(HttpServletRequest request){  //XML格式的消息数据  String respXml = "";  //默认返回的文本消息内容  String respContent = "未知的消息类型";  //调用parseXml方法解析请求消息  Map requestMap;  try {   requestMap = MessageUtil.parseXml(request);   //发送方账号   String fromUserName = requestMap.get("FromUserName");   //开发者微信号   String toUserName = requestMap.get("ToUserName");   //消息类型   String MsgType = requestMap.get("MsgType");      //回复文本消息   TextMessage textMessage = new TextMessage();   textMessage.setToUserName(fromUserName);   textMessage.setFromUserName(toUserName);   textMessage.setCreateTime(new Date().getTime());   textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);      if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)){   respContent = "您发送的是文本消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){   respContent = "您发送的是图片消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){   respContent = "您发送的是语音消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)){   respContent = "您发送的是视频消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)){   respContent = "您发送的是地理位置消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)){   respContent = "您发送的是链接消息";   }else if(MsgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)){   //事件类型   String eventType = requestMap.get("Event");   if(eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)){    respContent = "感谢您的关注";   }else if(eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)){    //TODO 取消订阅后用户不会再收到公众号发送的消息,因此不需要回复   }else if(eventType.equals(MessageUtil.EVENT_TYPE_SCAN)){    //TODO 处理扫描带参数二维码事件   }else if(eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)){    //TODO 处理上报地理位置事件   }else if(eventType.equals(MessageUtil.EVENT_TYPE_CLICK)){    //TODO 处理菜单点击事件   }   }   //设置文本消息的内容   textMessage.setContent(respContent);   //将文本消息对象转换成xml   respXml = MessageUtil.messageToXml(textMessage);  } catch (IOException e) {   // TODO Auto-generated catch block   e.printStackTrace();  }    return respXml;  } }

各种类型消息封装完成。

以上是“Java如何对微信各种类型消息进行封装”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注创新互联行业资讯频道!


新闻名称:Java如何对微信各种类型消息进行封装
文章源于:http://pwwzsj.com/article/jpecje.html