微信公众号开发(二)

接收微信的消息推送并且做出相应的处理

一、access_token的获取

微信公众号提供了很多接口给我们调用,调用这些接口都有一个前提,就是获取access_token。

关于access_token,在微信公众平台开发者文档上的获取接口调用凭据有比较详细的介绍:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,开发者需要妥善保存access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。并且每天调用获取access_token接口的上限是2000次。

关于access_token的获取方式,在微信公众平台开发者文档上有说明,公众号可以调用一个叫"获取access token"的接口来获取access_token。

获取access token接口调用请求说明

 http请求方式: GET

 请求的URL地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
 
 

这里获取access_token的方案是:定义一个默认启动servlet, 启动时建立一个无限循环的thread来获取,如果获取成功则休眠7000秒, 否则3秒后继续获取

package com.feng.web.service.servlet

import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.feng.web.model.AccessToken;
import com.feng.web.model.AccessTokenInfo;
import com.feng.web.service.util.NetUtil;

/**
 * 获取accessToken的Servlet
 * @author fengzp
 *
 */
@WebServlet(
         name = "AccessTokenServlet",
         urlPatterns = {"/AccessTokenServlet"},
         loadOnStartup = 1,
         initParams = {
                 @WebInitParam(name = "appId", value = ""),
                 @WebInitParam(name = "appSecret", value = "")
         })
public class AccessTokenServlet extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 7318150388093742524L;

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("AccessTokenServlet启动");
        
        final String appId = getInitParameter("appId");
        final String appSecret = getInitParameter("appSecret");
        
        new Thread(new Runnable() {
            public void run() {
                while(true){
                    try{
            
                        AccessTokenInfo.accessToken = getAccessToken(appId, appSecret);
                        if(AccessTokenInfo.accessToken != null){
                            System.out.println(AccessTokenInfo.accessToken.toString());
                            Thread.sleep(1000 * 7000);
                        }else{
                            Thread.sleep(1000 * 3);
                        }
                    }catch(Exception e){
                        System.out.println("发生异常:"+e.getMessage());
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }

    protected AccessToken getAccessToken(String appId, String appSecret) {
        //http请求方式: GET
        String url = String.format("https://api.weixin.qq.com/cgi-bin/token?"
                + "grant_type=client_credential&appid=%s&secret=%s", appId, appSecret);
        //{"access_token":"ACCESS_TOKEN","expires_in":7200}
        String result = NetUtil.HttpsRequest(url, "");
        System.out.println("获取到AccessToken: "+ result);
        
          //使用FastJson将Json字符串解析成Json对象
        JSONObject json = JSON.parseObject(result);
        AccessToken token = new AccessToken();
        token.setAccess_token(json.getString("access_token"));
        token.setExpires_in(json.getInteger("expires_in"));
        return token;
        
//        return GsonUtils.json2Bean(result, AccessToken.class);
    }
}

AccessToken

public class AccessToken {
    
    // 获取到的凭证
    private String access_token;
    // 凭证有效时间,单位:秒
    private int expires_in;
    public String getAccess_token() {
        return access_token;
    }
    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }
    public int getExpires_in() {
        return expires_in;
    }
    public void setExpires_in(int expires_in) {
        this.expires_in = expires_in;
    }
    @Override
    public String toString() {
        return "AccessToken [access_token=" + access_token + ", expires_in="
                + expires_in + "]";
    }
}

public class AccessTokenInfo {

    public static AccessToken accessToken = null;
}  

完成后部署运行,运行结果如下:

二、接受微信服务器发送的信息并回复

从微信公众平台接口接收消息指南中可以了解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的URL,而我们就需要在URL所指向的请求处理类WxServlet的doPost方法中接收消息和处理消息

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    
    String result = "";
    try {
        Map<String, String> map = WxMsgUtil.parseXml(request);
        WxMessage msg = (WxMessage) BeanUtil.map2Bean(WxMessage.class, map);
        System.out.println("用户发送的信息:"+msg.toString());
        WxMessage resultMsg = WxMsgUtil.buildRepeatMsg(msg);
        result = BeanUtil.bean2Xml(resultMsg, null);
        System.out.println("回复的信息:"+result);
        if(result.equals("")){
            result = "处理异常";
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("发生异常:"+e.getMessage());
    }
    response.getWriter().write(result);
}

WxMessage
package com.feng.web.model;

public class WxMessage {

    public static enum MessageType {
        TEXT, // 文本消息
        IMAGE, // 图片消息
        VOICE, // 语音消息
        VIDEO, // 视频消息
        SHORTVIDEO, // 小视频消息
        LOCATION, // 地理位置消息
        LINK, // 链接消息
        EVENT// 事件消息
    }

    private String ToUserName;
    private String FromUserName;
    private String CreateTime;
    private String MsgType;// text image voice video shortvideo location link
    private String MsgId;// 消息id,64位整型

    // text
    private String Content;
    
//    // image voice video:
//    private String MediaId;// 媒体id,可以调用多媒体文件下载接口拉取数据。
//    // image特有字段
//    private String PicUrl;// 图片链接
//    // voice特有字段
//    private String Format;// 语音格式,如amr,speex等
//    // video shortvideo特有字段
//    private String ThumbMediaId;// 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
    private Image Image;
    private Voice Voice;
    private Video Video;
    private Music Music;
    
    // location 特有字段
    private String Location_X;// 地理位置维度
    private String Location_Y;// 地理位置经度
    private String Scale;// 地图缩放大小
    private String Label;// 地理位置信息
    // link 特有字段
    private String Title;// 消息标题
    private String Description;// 消息描述
    private String Url;// 消息链接

    public Image getImage() {
        return Image;
    }

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

    public Voice getVoice() {
        return Voice;
    }

    public void setVoice(Voice voice) {
        Voice = voice;
    }

    public Video getVideo() {
        return Video;
    }

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

    public Music getMusic() {
        return Music;
    }

    public void setMusic(Music music) {
        Music = music;
    }

    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 String getCreateTime() {
        return CreateTime;
    }

    public void setCreateTime(String createTime) {
        CreateTime = createTime;
    }

    public String getMsgType() {
        return MsgType;
    }

    public void setMsgType(String msgType) {
        MsgType = msgType;
    }

    public String getContent() {
        return Content;
    }

    public void setContent(String content) {
        Content = content;
    }

    public String getMsgId() {
        return MsgId;
    }

    public void setMsgId(String msgId) {
        MsgId = msgId;
    }

    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;
    }

    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;
    }

    public static class Image{
        String mediaId;
        public String getMediaId() {
            return mediaId;
        }
        public void setMediaId(String mediaId) {
            this.mediaId = mediaId;
        }
    }
    public static class Voice{
        String mediaId;
        public String getMediaId() {
            return mediaId;
        }
        public void setMediaId(String mediaId) {
            this.mediaId = mediaId;
        }
    }
    public static class Video{
        String mediaId;
        String title;
        String description;
        public String getMediaId() {
            return mediaId;
        }
        public void setMediaId(String mediaId) {
            this.mediaId = mediaId;
        }
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
    }
    public static class Music{
        String title;
        String description;
        String MusicUrl;
        String HQMusicUrl;
        String ThumbMediaId;
        public String getTitle() {
            return title;
        }
        public void setTitle(String title) {
            this.title = title;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.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;
        }
    }
    
    @Override
    public String toString() {
        return "WxMessage [ToUserName=" + ToUserName + ", FromUserName="
                + FromUserName + ", CreateTime=" + CreateTime + ", MsgType="
                + MsgType + ", MsgId=" + MsgId + ", Content=" + Content
                + ", Image=" + Image + ", Voice=" + Voice + ", Video=" + Video
                + ", Music=" + Music + ", Location_X=" + Location_X
                + ", Location_Y=" + Location_Y + ", Scale=" + Scale
                + ", Label=" + Label + ", Title=" + Title + ", Description="
                + Description + ", Url=" + Url + "]";
    }
}

WxConfig

package com.feng.web.model;


public class WxConfig {

    public static String ImageMediaId = "1JcIX4cVYVjASjx-dv8yaJ8MIElTYSev8CoQ1rTLhwkTsxnM2n1v0zxBF1bEGir0";
    public static String VoiceMediaId = "Tr8zTacwl7kDUuF6c7IrAvmfWDkXcLmBCPJ7AApVKPL7rNeXV0TYUTS5Ne__uISd";
    public static String VideoMediaId = "YsgYy0KT1Mz0X9P1v5jxJttjockBgUNKn2z0_yz4l_KI5FhhTWBHJalTOe-CZ8Ig";
    
    //http请求方式: POST/FORM,需使用https
    public static final String UPLOAD_MEDIA = "https://api.weixin.qq.com/cgi-bin/media/upload";
    //http请求方式: GET,https调用
    public static final String DOWNLOAD_MEDIA = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s";
}

下面是我自己写的一些工具类:

WxMsgUtil
package com.feng.web.service.util;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

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

import com.feng.web.model.WxConfig;
import com.feng.web.model.WxMessage;
import com.feng.web.model.WxMessage.Image;
import com.feng.web.model.WxMessage.MessageType;
import com.feng.web.model.WxMessage.Voice;

public class WxMsgUtil {
    
    public static WxMessage buildRepeatMsg(WxMessage msg){
        WxMessage result = new WxMessage();
        result.setFromUserName(msg.getToUserName());
        result.setToUserName(msg.getFromUserName());
        result.setCreateTime(getUtcTime());
        
        result = buildTestMsg(result, msg.getContent());
        
        return result;
    }
    
    private static WxMessage buildTestMsg(WxMessage result, String content) {
        if(content.equals("文本")){
            result.setContent("Hi!");
            result.setMsgType(MessageType.TEXT.name());
        }else if(content.equals("音乐")){
            Voice voice = new Voice();
            voice.setMediaId(WxConfig.VoiceMediaId);
            result.setVoice(voice);
            result.setMsgType(MessageType.VOICE.name());
        }else if(content.equals("图片")){
            Image image = new Image();
            image.setMediaId(WxConfig.ImageMediaId);
            result.setImage(image);
            result.setMsgType(MessageType.IMAGE.name());
        }else{
            result.setContent("请输入文本、音乐、图片");
            result.setMsgType(MessageType.TEXT.name());
        }
        
        return result;
    }
    

    private static String getUtcTime() {
        Date dt = new Date();// 如果不需要格式,可直接用dt,dt就是当前系统时间
        DateFormat df = new SimpleDateFormat("yyyyMMddhhmm");// 设置显示格式
        String nowTime = df.format(dt);
        long dd = (long) 0;
        try {
            dd = df.parse(nowTime).getTime();
        } catch (Exception e) {

        }
        return String.valueOf(dd);
    }

    /**
     * 解析微信发来的请求(XML)
     * @param request
     * @return map
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static Map<String,String> parseXml(HttpServletRequest request) {
        try {
            // 将解析结果存储在HashMap中
            Map<String,String> map = new HashMap<String,String>();
            // 从request中取得输入流
            InputStream inputStream = request.getInputStream();
            System.out.println("获取输入流");
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
    
            // 遍历所有子节点
            for (Element e : elementList) {
                System.out.println(e.getName() + "|" + e.getText());
                map.put(e.getName(), e.getText());
            }
    
            // 释放资源
            inputStream.close();
            inputStream = null;
            return map;
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (DocumentException e1) {
            e1.printStackTrace();
        }
        return null;
    }
    
    public static String bean2Xml(WxMessage msg){
        StringBuffer buffer  = new StringBuffer();
        buffer.append("<xml>");
        
        Map<String, Object> p = BeanUtil.bean2Map(msg);
        Set<String> s = p.keySet();
        Iterator<String> i = s.iterator();
        
        while (i.hasNext()){
            String key = i.next();
            if(key.equals("class")){}
            else {
                Object value = p.get(key);
                String name = key.substring(0, 1).toUpperCase() + key.substring(1);
                buffer.append("<");
                buffer.append(name);
                buffer.append(">");
                if(value == null || value.toString().equals("")){
                    buffer.append("");
                } else {
                    buffer.append(value);
                }
                buffer.append("</");
                buffer.append(name);
                buffer.append(">");
            }
        }
        
        buffer.append("</xml>");
        return buffer.toString();
    }
}

BeanUtil

package com.feng.web.service.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

/**
 * 需要jdom.jar
 * @author fengzp
 * 2016年5月17日上午10:37:26
 */
public class BeanUtil{
    
    /**
     * 把Bean转成Map
     */
    public static Map<String, Object> bean2Map(Object bean)  {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            Map<String, Object> fields = new HashMap<String, Object>();
            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                fields.put(pd.getName(), pd.getReadMethod().invoke(bean));
            }
            return fields;
        } catch (IntrospectionException ex) {
            throw new RuntimeException(ex);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException(ex);
        }
    }
    
    public static Object map2Bean(Class<?> clazz, Map<String, String> map) {  
        return map2Bean(clazz, map, true);
    }
    
    public static Object map2Bean(Class<?> clazz, Map<String, String> map, boolean toUpper) {  
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz); // 获取类属性  
            Object obj = clazz.newInstance(); // 创建 JavaBean 对象  
      
            // 给 JavaBean 对象的属性赋值  
            PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();  
            for (int i = 0; i< propertyDescriptors.length; i++) {  
                PropertyDescriptor descriptor = propertyDescriptors[i];  
                String propertyName = descriptor.getName();  
                if(toUpper)
                    propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                if (map.containsKey(propertyName)) {  
                    // 下面一句可以 try 起来,这样当一个属性赋值失败的时候就不会影响其他属性赋值。  
                    String value = map.get(propertyName);  
                    
                    descriptor.getWriteMethod().invoke(obj, value);
                }  
            }  
            return obj;  
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("map2bean转换异常");
        }  
        return null;
    }
    
    public static String bean2Xml(Object obj) throws InstantiationException  { 
        return bean2Xml(obj, null);
    }
    
    /**
     * 1.<strong>bean类的属性必须有getter、setter方法</strong> 
     * 2.<strong>生成的xml不会设置到xml的属性</strong> 
     */
    @SuppressWarnings("unchecked")
    public static String bean2Xml(Object obj,String root) throws InstantiationException  {  
        //加这一句判断是为了方便递归调用,如果root为空,那么视为第一次调用,也就是xml的根  
        if(root==null || root.trim().equals("")){  
            root = "xml";  
        }  
        if(root.equalsIgnoreCase("item")){  
            ////、!!为什么只有这个以的item的i是小写的,其他的标签都是第一个字符大写的。why  
            root = root.toLowerCase();  
        }  
              
        try {  
        //声明一个列表 存放需要转换成xml类的所有设计的父类  
        //这个地方没有涉及到属性为类的地方,应为下面的处理方法是,如果属性是类的话,就递归调用这个方法,所以没有什么需要担心的  
        List<Class<?>> cl = new ArrayList<Class<?>>();  
          
        //获取对象的类  
        Class<?> clazz = obj.getClass();  
          
        //判断,如果父类不是Object的话把所有的类放到上面声明的list里面   
        String simpleName = clazz.getSimpleName();  
          
        while (!"Object".equals(simpleName)) {  
            cl.add(clazz);  
            clazz = clazz.getSuperclass();  
            simpleName = clazz.getSimpleName();  
        }  
        //上面是从子类开始存放的,所以这里要反转  
        Collections.reverse(cl);  
          
        //开始创建xml  
        StringBuffer xml = new StringBuffer("<"+root+">
");  
          
        for (Class<?> cz : cl) {  
            //System.out.println("list  " + cz.getName());  
            //获取类里面声明的所有属性,之所以上面要获取父级的类,时应为这里只能获取当前类的声明方法,无法获取到集成来的方法  
            Field[] fs = cz.getDeclaredFields();  
            for (Field f : fs) {  
                //获取属性的类型  
                Class<?> ct =f.getType();  
                //获取类对应的名称  
                String ctName = ct.getSimpleName();  
                String fName = f.getName();  
                String firstUpperName = fName.substring(0, 1).toUpperCase()+fName.substring(1);  
                  
                //System.out.println();  
                //当然,如果类是基础类型的直接设值就可以了  
                if("int".equals(ctName) || "long".equals(ctName)|| "double".equals(ctName)|| "float".equals(ctName) || "char".equals(ctName)){  
                    xml.append(getFieldXml(f,cz,obj)).append("
");  
                }else if("String".equals(ctName)||"char".equals(ctName)){  
                    xml.append(getFieldXml(f,cz,obj)).append("
");  
                }else {  
                    //如果属性不是基础类型的,则需要递归调用,也就是把上面的方法冲走一遍  
                    //通过执行get方法,获取对象的返回值。  
                    String methodName = "get" +firstUpperName;  
                    Class<?>[] cnull = null;  
                    Method m=cz.getMethod(methodName, cnull);  
                    Object[] osnull =null;  
                    Object reto=m.invoke(obj, osnull);  
                      
                    if(null!=reto){  
                        if(reto instanceof Collection<?>){  
                            //如果结果是集合类型,那么获取子元素继续  
                            xml.append("<"+firstUpperName+">
");  
                            Collection<Object> ol = (Collection<Object>)reto;  
                            for(Object o:ol){  
                                xml.append(bean2Xml(o,o.getClass().getSimpleName()));  
                            }  
                              
                            xml.append("</"+firstUpperName+">
");  
                        }else if(reto instanceof Array){  
                            //如果结果是数组类型,那么获取数组里每个元素继续  
                            xml.append("<"+firstUpperName+">
");  
                            Object[] ol = (Object[])reto;  
                            for(Object o:ol){  
                                xml.append(bean2Xml(o,o.getClass().getSimpleName()));  
                            }  
                              
                            xml.append("</"+firstUpperName+">
");  
                        } else{  
                            //如果返回值不为null 执行递归调用  
                            xml.append(bean2Xml(reto,ctName));  
                        }  
                    }else{  
                        //如果为null,直接在这个属性里面设置为空就可以了  
                        xml.append("<"+firstUpperName+">
</"+firstUpperName+">
");  
                    }  
                }  
            }  
              
        }  
        xml.append("</"+root+">
");  
          
        return xml.toString();  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        } catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        }   
        return null;  
    }  
  
    /** 
     * 通过Filed,Class,和Objec对象获取需要生成的对应Filed的字符串 
     */  
    private static String getFieldXml(Field f, Class<?> cz, Object obj) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{  
        String fName = f.getName();  
          
        String firstUpperName = fName.substring(0, 1).toUpperCase()+fName.substring(1);  
        String str = "<"+firstUpperName+">";  
          
        String methodName = "get" +firstUpperName;  
          
        System.out.println(fName+"  "+methodName);   
        Class<?>[] cnull = null;  
        Method m=cz.getMethod(methodName, cnull);  
        Object[] osnull =null;  
        Object reto=m.invoke(obj, osnull);  
        if(null!=reto){  
              
            Class<?> ct =f.getType();  
            String ctName = ct.getSimpleName();  
            if("int".equals(ctName) || "long".equals(ctName)){  
                if("0".equals(reto.toString())){  
                    System.err.println(fName +" 对应的值为0");  
                }  
                str +=reto.toString();  
            }else if("double".equals(ctName)|| "float".equals(ctName)){  
                if("0.0".equals(reto.toString())||"0".equals(reto.toString())){  
                    System.err.println(fName +" 对应的值为0");  
                }  
                str +=reto.toString();  
            }else{  
                str +="<![CDATA["+reto.toString()+"]]>";  
            }  
        }else{  
            System.err.println(fName +" 对应的值为空");  
        }  
        str +="</"+firstUpperName+">";  
        return str;  
    }  
      
    /** 
     * 通过xml字符串转换成给定类的对象 
     * <br> 
     * 1.转换过程中不会操作任何xml的属性操作,值是一个标签对应一个属性来操作的 
     * <br> 
     * 2.参数Class<?> c对应的类,需要设置的属性都必须有getter,setter方法 
     */  
    public static <T> T xml2Bean(String xml, Class<T> c) {  
        T t = null;  
        try {  
            t= c.newInstance();  
            SAXBuilder sb = new SAXBuilder();  
            StringReader read = new StringReader(xml);  
            InputSource source = new InputSource(read);  
            Document doc = sb.build(source);  
            Element root =doc.getRootElement();  
            convery(root,c,t);  
              
              
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
  
        return t;  
    }  
  
    @SuppressWarnings("unchecked")
    private static void convery(Element e,Class<?> clazz,Object o) throws SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{  
        String en =e.getName();  
        if("xml".equals(en)){  
            List<Element> el = e.getChildren();  
            for(Element e1:el){  
                convery(e1,clazz,o);  
            }  
        }else{  
            List<Element> el = e.getChildren();  
            if(el.size()>0){  
                String childClassName =e.getName();  
                  
                String methodName = "get" +childClassName.substring(0, 1).toUpperCase()+childClassName.substring(1);  
                  
                Class<?> clazz1 = null;  
                Method[] ms = clazz.getMethods();  
                for(Method m:ms){  
//                  System.out.println(m.getName());  
                    if(methodName.equals(m.getName())){  
                        clazz1 = m.getReturnType();  
                    }  
                }  
//              try {  
//                  clazz1 = Class.forName(ncn);  
//              } catch (Exception e2) {  
//                  System.err.println(ncn + " 实例化失败,请检查是否存在这个类 ");  
//              }  
                if(null==clazz1){  
                    //没有找到对应的类,这里只是忽略  
                    System.out.println(methodName + " 方法未找到,或者返回类型不正确 ");  
                    return;  
                }  
                Object o1 = clazz1.newInstance();  
                  
                try {  
                    //反射获取set方法,帮o1的值设置进o里面  
                    Method m =clazz.getMethod(methodName, clazz1);  
                    m.invoke(o, o1);  
                } catch (Exception e2) {  
                    //应该是没有找到对应的方法,忽略  
                    System.err.println(methodName +" 方法调用失败,请检查方法是否存在");  
                    return ;  
                }  
                  
                for(Element e1:el){  
                    convery(e1,clazz1,o1);  
                }  
            }else{  
                String eName = e.getName();  
                String methodName = "set" +eName.substring(0, 1).toUpperCase()+eName.substring(1);  
                Method[] ms=clazz.getMethods();  
                for(Method m:ms){  
                    if(m.getName().equals(methodName)){  
                        Class<?>[] c= m.getParameterTypes();  
                        //目前只支持带一个参数的情况  
                        String text = e.getTextTrim();  
                        Object v = null;  
                        String cn = c[0].getSimpleName();  
                          
                        if("int".equals(cn)){  
                            v = Integer.parseInt(text);  
                        }else if("long".equals(cn)){  
                            v= Long.parseLong(text);  
                        }else if("double".equals(cn)){  
                            v = Double.parseDouble(text);  
                        }else if("float".equals(cn)){  
                            v = Float.parseFloat(text);  
                        }else{  
                            v = text;  
                        }  
                        m.invoke(o,v);  
                    }  
                }  
            }  
        }  
    }  
}

NetUtil
package com.feng.web.service.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class NetUtil {

    public static String HttpsRequest(String reqUrl, String requestMethod) {
        URL url;
        InputStream is;
        String resultData = "";

        try {
            url = new URL(reqUrl);
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            TrustManager[] tm = { new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkServerTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {

                }

                public void checkClientTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {

                }
            } };

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, tm, null);
            con.setSSLSocketFactory(ctx.getSocketFactory());
            con.setHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            con.setDoInput(true); // 允许输入流,即允许下载

            con.setDoOutput(false); // 允许输出流,即允许上传
            con.setUseCaches(false); // 不使用缓冲

            if (null != requestMethod && !requestMethod.equals("")) {
                con.setRequestMethod(requestMethod); // 使用指定的方式
            } else {
                con.setRequestMethod("GET"); // 使用get请求
            }
            is = con.getInputStream(); // 获取输入流,此时才真正建立链接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine;
            while ((inputLine = bufferReader.readLine()) != null) {
                if(!inputLine.equals("") && !inputLine.equals("null"))
                    resultData += inputLine + "
";
            }
            System.out.println(resultData);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        return resultData;
    }
    
    public static File download(String fileName, String path, String method, String body){
        if (fileName == null || path == null || method == null) {
            return null;
        }

        File file = null;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        FileOutputStream fileOut = null;
        try {
            URL url = new URL(path);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod(method);
            if (null != body) {
                OutputStream outputStream = conn.getOutputStream();
                outputStream.write(body.getBytes("UTF-8"));
                outputStream.close();
            }

            inputStream = conn.getInputStream();
            if (inputStream != null) {
                file = new File(fileName);
            } else {
                return file;
            }

            //写入到文件
            fileOut = new FileOutputStream(file);
            if (fileOut != null) {
                int c = inputStream.read();
                while (c != -1) {
                    fileOut.write(c);
                    c = inputStream.read();
                }
            }
        } catch (Exception e) {
        } finally {
            if (conn != null) {
                conn.disconnect();
            }

            /*
             * 必须关闭文件流
             * 否则JDK运行时,文件被占用其他进程无法访问
             */
            try {
                inputStream.close();
                fileOut.close();
            } catch (IOException execption) {
            }
        }
        return file;
    }
}

关注微信公众号后,测试,结果如下

上面可能有一点是比较疑惑的,就是MediaId是怎么来的,其实通过微信公众号平台提供的素材管理接口将图片,语音,视频上传到微信服务器上,上传成功后,微信服务器会给我们返回一个
mediaId,用于标识上传成功的多媒体素材,上传素材的代码如下:

package com.feng.web.service.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;

import com.feng.web.model.WxConfig;
import com.feng.web.model.WxMessage;

public class WxMediaUtil {
    
    private static final String token = "NyTgtiz3-g6fRFqq3MQQ6TJ-C0Fd1-Loh7ZG34e8dKk7ycslWrpcfwh06-nbjoa5ZqxcOaerjG3PD2QlWWSXnziBici1j1rj_gMRCI5BjrbwDFOWxnjtzR0YeeDIzWkfMVPhAHAIRL";
    
    public static void main(String[] args) {
        File file = new File("C:/Users/feng/Desktop/feng/2.JPG");
        String result = WxMediaUtil.upload(WxMessage.MessageType.IMAGE.name(), file);
        
//        File file = new File("C:/Users/feng/Desktop/feng/1.mp3");
//        String result = WxMediaUtil.upload(WxMessage.MessageType.VOICE.name(), file);
        
//        File file = new File("C:/Users/feng/Desktop/feng/apple.mp4");
//        String result = WxMediaUtil.upload(WxMessage.MessageType.VIDEO.name(), file);
        System.out.println(result);
        
        //Q--HOiK8Ye5foHegBcqrpeNtzKgy6m-y-3dDLWTOyOwaqBf_u-9kr4DsJkXOH5TO
        //Tr8zTacwl7kDUuF6c7IrAvmfWDkXcLmBCPJ7AApVKPL7rNeXV0TYUTS5Ne__uISd
        //YsgYy0KT1Mz0X9P1v5jxJttjockBgUNKn2z0_yz4l_KI5FhhTWBHJalTOe-CZ8Ig
//        String id = "niArEt9PIAkLNaUJPUproo89UqAgkNY7xUjzWYBAw64TLv5cZW-hI6FsnD06JDjf";
//        String name = id+".mp4";
//        File file = download("C:/Users/feng/Desktop/down/"+name, String.format(DOWNLOAD_MEDIA, token, id), "GET", null);
//        System.out.println(file.getName());
    }
    
    @SuppressWarnings("deprecation")
    public static String upload(String type, File file) {
        String result = "";

        if (file == null || token == null || type == null) {
            return null;
        }

        if (!file.exists()) {
            System.out.println("上传文件不存在,请检查!");
            return null;
        }

        String url = WxConfig.UPLOAD_MEDIA;
        // JSONObject jsonObject = null;
        PostMethod post = new PostMethod(url);
        post.setRequestHeader("Connection", "Keep-Alive");
        post.setRequestHeader("Cache-Control", "no-cache");
        FilePart media;
        HttpClient httpClient = new HttpClient();
        // 信任任何类型的证书
        Protocol myhttps = new Protocol("https", new SSLProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", myhttps);

        try {
            media = new FilePart("media", file);
            Part[] parts = new Part[] { new StringPart("access_token", token), new StringPart("type", type), media };
            MultipartRequestEntity entity = new MultipartRequestEntity(parts, post.getParams());
            post.setRequestEntity(entity);
            int status = httpClient.executeMethod(post);
            if (status == HttpStatus.SC_OK) {
                result = post.getResponseBodyAsString();
                // jsonObject = JSONObject.parseObject(text);
            } else {
                System.out.println("upload Media failure status is:" + status);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }
}
原文地址:https://www.cnblogs.com/andyfengzp/p/6019688.html