java版本微信jssdk蒜哀、微信驗(yàn)證簽名demo(Servlet)

開發(fā)背景

  1. 最近在學(xué)習(xí)java斩箫,所以從網(wǎng)上看了一些別人的代碼,再加入了自己的一些理解撵儿,主要是擔(dān)心之后會(huì)忘記乘客,所以寫下一篇東西記錄一下思路。

一淀歇、 獲取acess_token以及jsapiTicket

  1. 新建一個(gè)類TokenThread易核,實(shí)現(xiàn)線程的Runnable接口,代碼如下:

TokenThread

package util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import model.AccessToken;
import model.JsapiTicket;

/**
 * Created by xu on 2017/7/10.
 */
public class TokenThread implements Runnable {
    public static String appId = "xxx";

    public static String appSecret= "xxx";

    public static AccessToken accessToken = null;

    public static JsapiTicket jsapiTicket = null;

    public final static String js_api_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";


    @Override
    public void run() {
        while (true) {
            try {
                accessToken = this.getAccessToken();
                jsapiTicket = this.getJsapiTicket();
                //獲取到accessToken后浪默,休眠7000秒牡直,保證不會(huì)重復(fù)的獲取,超過了每天的最大次數(shù)
                if (null != accessToken) {
                    System.out.println(accessToken.getAccessToken());
                    System.out.println(jsapiTicket.getJsapiTicket());
                    Thread.sleep(7000 * 1000); //獲取到access_token 休眠7000秒

                } else {
                    Thread.sleep(1000 * 3); //獲取的access_token為空 休眠3秒
                }
            } catch (Exception e) {
                System.out.println("發(fā)生異常:" + e.getMessage());
                e.printStackTrace();
                try {
                    Thread.sleep(1000 * 10); //發(fā)生異常休眠1秒
                } catch (Exception e1) {

                }
            }
        }
    }

    /**
     * 獲取access_token
     * @return
     */
    private AccessToken getAccessToken(){
        NetWorkHelper netHelper = new NetWorkHelper();
        String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",this.appId,this.appSecret);
        String result = netHelper.getHttpsResponse(Url,"");
        System.out.println(result);

        //response.getWriter().println(result);
        JSONObject json = JSONObject.parseObject(result);
        System.out.println(json);

        AccessToken token = new AccessToken();
        token.setAccessToken(json.getString("access_token"));
        token.setExpiresin(json.getInteger("expires_in"));
        return token;
    }

    /**
     * 獲取jsapi_ticket
     * @return
     */
    private JsapiTicket getJsapiTicket(){
        NetWorkHelper netHelper = new NetWorkHelper();
        String Url = js_api_ticket_url.replace("ACCESS_TOKEN",this.getAccessToken().getAccessToken());
        String result = netHelper.getHttpsResponse(Url,"");
        System.out.println(result);
        JSONObject json = JSONObject.parseObject(result);
        System.out.println(json);

        JsapiTicket jsapiTicket = new JsapiTicket();
        jsapiTicket.setJsapiTicket(json.getString("ticket"));
        jsapiTicket.setExpiresin(json.getInteger("expires_in"));

        return jsapiTicket;
    }

}

這里用到了兩個(gè)工具類NetWorkHelper纳决,發(fā)起網(wǎng)絡(luò)請(qǐng)求網(wǎng)上有封裝好的碰逸,我做一下搬運(yùn)工:

NetWorkHelper

package util;

import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Created by xu on 2017/7/10.
 */
public class NetWorkHelper {
    public String getHttpsResponse(String hsUrl,String requestMethod) {
        URL url;
        InputStream is = null;
        String resultData = "";
        try {
            url = new URL(hsUrl);
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            TrustManager[] tm = {xtm};

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, tm, null);

            con.setSSLSocketFactory(ctx.getSocketFactory());
            con.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });


            con.setDoInput(true); //允許輸入流,即允許下載

            //在android中必須將此項(xiàng)設(shè)置為false
            con.setDoOutput(false); //允許輸出流阔加,即允許上傳
            con.setUseCaches(false); //不使用緩沖
            if(null!=requestMethod && !requestMethod.equals("")) {
                con.setRequestMethod(requestMethod); //使用指定的方式
            }
            else{
                con.setRequestMethod("GET"); //使用get請(qǐng)求
            }
            is = con.getInputStream(); //獲取輸入流饵史,此時(shí)才真正建立鏈接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine = "";
            while ((inputLine = bufferReader.readLine()) != null) {
                resultData += inputLine + "\n";
            }
            System.out.println(resultData);


            Certificate[] certs = con.getServerCertificates();

            int certNum = 1;

            for (Certificate cert : certs) {
                X509Certificate xcert = (X509Certificate) cert;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultData;
    }

    X509TrustManager xtm = new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
            // TODO Auto-generated method stub

        }
    };
}

上面還引入了阿里巴巴的json解析包import com.alibaba.fastjson.JSONObject;自行上網(wǎng)搜索就好。
上面的獲取accessToken的過程中,new了一個(gè)AccessToken和JsapiTicket對(duì)象胳喷,我把她們放進(jìn)了一個(gè)model類里湃番。

AccessToken

package model;

/**
 * Created by xu on 2017/7/10.
 */
public class AccessToken {
    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresin() {
        return expiresin;
    }

    public void setExpiresin(int expiresin) {
        this.expiresin = expiresin;
    }

    private String accessToken;

    private int expiresin;
}

JsapiTicket

package model;

/**
 * Created by xu on 2017/7/12.
 */
public class JsapiTicket {

    private String jsapiTicket;

    private int expiresin;

    public String getJsapiTicket() {
        return jsapiTicket;
    }

    public void setJsapiTicket(String jsapiTicket) {
        this.jsapiTicket = jsapiTicket;
    }

    public int getExpiresin() {
        return expiresin;
    }

    public void setExpiresin(int expiresin) {
        this.expiresin = expiresin;
    }

}

新建一個(gè)HttpServlet,AccessTokenServlet厌蔽,用來執(zhí)行獲取牵辣,初始化的過程中執(zhí)行,這里需要配置web.xml

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>wechatServlet</servlet-name>
        <servlet-class>com.wecahtServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>wechatServlet</servlet-name>
        <url-pattern>/wechat</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>GetConfigServlet</servlet-name>
        <servlet-class>com.GetConfigServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>GetConfigServlet</servlet-name>
        <url-pattern>/getConfig</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>ReturnRobotServlet</servlet-name>
        <servlet-class>com.ReturnRobotServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ReturnRobotServlet</servlet-name>
        <url-pattern>/doReturn</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>initAccessTokenServlet</servlet-name>
        <servlet-class>
            com.AccessTokenServlet
        </servlet-class>
        <init-param>
            <param-name>appid</param-name>
            <param-value>xxxx</param-value>
        </init-param>
        <init-param>
            <param-name>appsecret</param-name>
            <param-value>xxxx</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <welcome-file-list>
        <welcome-file>returnRobot.jsp</welcome-file>
    </welcome-file-list>
</web-app>

AccessTokenServlet

package com;

import util.TokenThread;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by xu on 2017/7/10.
 */
@WebServlet(name = "AccessTokenServlet")
public class AccessTokenServlet extends HttpServlet {

    public void init() throws ServletException {
        TokenThread.appId = getInitParameter("appid"); //獲取servlet初始參數(shù)appid和appsecret
        TokenThread.appSecret = getInitParameter("appsecret");
        System.out.println("appid:"+TokenThread.appId);
        System.out.println("appSecret:"+TokenThread.appSecret);
        new Thread(new TokenThread()).start(); //啟動(dòng)進(jìn)程
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

二奴饮、獲取jssdk配置

  1. 創(chuàng)建一個(gè)GetConfigServlet用以頁面獲取jssdk的配置信息

GetConfigServlet

package com;

import com.alibaba.fastjson.JSON;
import util.Sign;
import util.TokenThread;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by xu on 2017/7/12.
 */
@WebServlet(name = "GetConfigServlet")
public class GetConfigServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String url = request.getParameter("url");
        String jsapi_tickec = TokenThread.jsapiTicket.getJsapiTicket();
        Map<String, String> jssdk = Sign.main(jsapi_tickec,url);
        String str = JSON.toJSONString(jssdk);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.write(str);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("get config test success");
    }
}

上文中引用了sign工具類:

Sign

package util;

import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

public class Sign {
    public static Map<String, String> main(String jsapiTicket,String posturl) {
        String jsapi_ticket = jsapiTicket;

        // 注意 URL 一定要?jiǎng)討B(tài)獲取纬向,不能 hardcode
        String url = posturl;
        Map<String, String> ret = sign(jsapi_ticket, url);
//        for (Map.Entry entry : ret.entrySet()) {
//            System.out.println(entry.getKey() + ", " + entry.getValue());
//        }
        return ret;
    };

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意這里參數(shù)名必須全部小寫,且必須有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        System.out.println(string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("appId", TokenThread.appId);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

前段js:

$(document).ready(function () {
    //獲取配置信息
    $.ajax({
        url : "http://120.77.43.103/wechat/getConfig",
        type : 'post',
        dataType : 'json',
        contentType : "application/x-www-form-urlencoded; charset=utf-8",
        data : {
            'url' : location.href.split('#')[0]
        },
        success : function(data) {
            console.log(data);
            wx.config({
                debug : true,
                appId : data.appId,
                timestamp : data.timestamp,
                nonceStr : data.nonceStr,
                signature : data.signature,
                jsApiList : [ 'checkJsApi', 'onMenuShareTimeline',
                    'onMenuShareAppMessage', 'onMenuShareQQ',
                    'onMenuShareWeibo', 'hideMenuItems',
                    'showMenuItems', 'hideAllNonBaseMenuItem',
                    'showAllNonBaseMenuItem', 'translateVoice',
                    'startRecord', 'stopRecord', 'onRecordEnd',
                    'playVoice', 'pauseVoice', 'stopVoice',
                    'uploadVoice', 'downloadVoice', 'chooseImage',
                    'previewImage', 'uploadImage', 'downloadImage',
                    'getNetworkType', 'openLocation', 'getLocation',
                    'hideOptionMenu', 'showOptionMenu', 'closeWindow',
                    'scanQRCode', 'chooseWXPay',
                    'openProductSpecificView', 'addCard', 'chooseCard',
                    'openCard' ]
            });
        },
        error: function (xhr, type) {
            showAlert("getJSSDKSignature出錯(cuò)");
        },
    });
    checkUserDeposit();
});
function checkUserDeposit() {
    wx.ready(function () {
        scanQRCode();
    });
}
function scanQRCode() {
    wx.scanQRCode({
        needResult: 1, // 默認(rèn)為0戴卜,掃描結(jié)果由微信處理逾条,1則直接返回掃描結(jié)果,
        scanType: ["qrCode", "barCode"], // 可以指定掃二維碼還是一維碼投剥,默認(rèn)二者都有
        success: function (res) {
            var result = res.resultStr; // 當(dāng)needResult 為 1 時(shí)师脂,掃碼返回的結(jié)果
            //var result = "linuxserl.honeybot.cn:5120/download/?id=bind@104@10V1BLH100040478054";
            //var result = "CODE_128,10V1BLH100261";
            var postCode = "";
            var robotCodeType = 0;
            if (result.indexOf(",") > -1) {
                //條形碼
                var codes = result.split(',');
                if (codes != null && codes.length > 1) {
                    postCode = codes[1];
                    robotCodeType = 1;
                }
            } else {
                //二維碼
                var reg = /@(.*?)@/;
                var codes = reg.exec(result);
                if (codes.length > 1) {
                    postCode = codes[1];
                    robotCodeType = 0;
                }
            }
            showConfirm("是否確認(rèn)退還?",
                function () {
                    returnRobot(robotCodeType, postCode);
                });
        }
    });
}
function returnRobot(robotCodeType, robotCodeValue) {
    var dialogLoading = null;
    var postData = {
        robot_code:
        {
            robot_code_type: robotCodeType,
            robot_code_value: robotCodeValue
        }
    }
    $.ajax({
        type: 'POST',
        cache: false,
        url: "http://120.77.43.103/wechat/doReturn",
        data: "json_body=" + JSON.stringify(postData),
        dataType: 'json',
        beforeSend: function (XHR) {
            dialogLoading = showLoading();
        },
        success: function (data) {
            if (data.result_code == 0) {
                setTimeout(function() {
                    showAlert("申請(qǐng)退還機(jī)器人成功江锨,請(qǐng)點(diǎn)擊確定支付租金", function () {
                        goTo(config.page_url.return_robot_wait_confrm);
                    });
                }, 500);

            } else {
                setTimeout(function () {
                    showAlert(data.result_message);
                }, 500);

            }
        },
        error: function (xhr, type) {
            showAlert('error')
        },
        complete: function (xhr, type) {
            dialogLoading.hide();
        }
    });
}
wx.error(function (res) {
    showAlert("微信接口出錯(cuò)");
});

三吃警、額外的一些簽名,驗(yàn)證配置

wecahtServlet

package com;

import com.sun.tools.classfile.Signature;
import util.CheckUtil;
import util.Sign;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by xu on 2017/7/10.
 */
@WebServlet(name = "wecahtServlet")
public class wecahtServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if( CheckUtil.checkSignature(signature,timestamp,nonce))
        {
            response.getWriter().println(echostr);
        }
    }

}

工具類CheckUtil

package util;

import java.util.Arrays;

/**
 * Created by xu on 2017/7/10.
 */
public class CheckUtil
{
    private static final String token = "test";
    public static boolean checkSignature(String signature,String timestamp,String nonce)
    {
        String[] arr = new String[]{token,timestamp,nonce};
        //排序
        Arrays.sort(arr);
        //生成字符串
        StringBuffer content = new StringBuffer();
        for (int i=0;i<arr.length;i++)
        {
            content.append(arr[i]);
        }
        //sha1加密
        String temp = Decript.SHA1(content.toString());
        //校驗(yàn)簽名
        return temp.equals(signature);
    }
}

sha1

package util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by xu on 2017/7/10.
 */
public class Decript {
    public static String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字節(jié)數(shù)組轉(zhuǎn)換為 十六進(jìn)制 數(shù)
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}

引用JdbcUtils jdbc連接工具類

package util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcUtils
{
    private static String url="jdbc:mysql://xxx.xxx.xxx/weixin?useUnicode=true&characterEncoding=utf-8";
    private static String user="xxx";
    private static String password="xxx";
    private JdbcUtils()
    {
    }
    static
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
        }
        catch(ClassNotFoundException e)
        {
            throw new ExceptionInInitializerError(e);
        }
    }
    public static Connection getConnection() throws SQLException
    {
        return DriverManager.getConnection(url, user, password);
    }
    public static void free(ResultSet resultset,Statement st,Connection conn)
    {
        //6.釋放資源

        try{
            if(resultset!=null)
                resultset.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if(st!=null)
                    st.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally
            {
                if(conn!=null)
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            }
        }
    }
}

完整項(xiàng)目地址:https://github.com/345632699/java-jssdk

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啄育,一起剝皮案震驚了整個(gè)濱河市酌心,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挑豌,老刑警劉巖安券,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異氓英,居然都是意外死亡侯勉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門铝阐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來址貌,“玉大人,你說我怎么就攤上這事徘键》际模” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵啊鸭,是天一觀的道長。 經(jīng)常有香客問我匿值,道長赠制,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮钟些,結(jié)果婚禮上烟号,老公的妹妹穿的比我還像新娘。我一直安慰自己政恍,他們只是感情好汪拥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著篙耗,像睡著了一般迫筑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宗弯,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天脯燃,我揣著相機(jī)與錄音,去河邊找鬼蒙保。 笑死辕棚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的邓厕。 我是一名探鬼主播逝嚎,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼详恼!你這毒婦竟也來了补君?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤单雾,失蹤者是張志新(化名)和其女友劉穎赚哗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硅堆,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屿储,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渐逃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片够掠。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茄菊,靈堂內(nèi)的尸體忽然破棺而出疯潭,到底是詐尸還是另有隱情,我是刑警寧澤面殖,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布竖哩,位于F島的核電站,受9級(jí)特大地震影響脊僚,放射性物質(zhì)發(fā)生泄漏相叁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望增淹。 院中可真熱鬧椿访,春花似錦、人聲如沸虑润。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽根灯。三九已至低千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舞蔽,已是汗流浹背荣病。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渗柿,地道東北人个盆。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像朵栖,于是被迫代替她去往敵國和親颊亮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法陨溅,類相關(guān)的語法终惑,內(nèi)部類的語法,繼承相關(guān)的語法门扇,異常的語法雹有,線程的語...
    子非魚_t_閱讀 31,639評(píng)論 18 399
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)臼寄,斷路器霸奕,智...
    卡卡羅2017閱讀 134,662評(píng)論 18 139
  • 會(huì)說話的領(lǐng)導(dǎo)留攒,員工一定干勁十足煤惩;會(huì)說話的員工,工作一定風(fēng)生水起炼邀;會(huì)說話的夫妻魄揉,家庭一定和諧美滿; 如果人人說話都帶...
    Miss墨菲閱讀 464評(píng)論 6 9
  • 作者:亞馬遜的蝴蝶(Butterfly_of_Amazon) (2017年3月11日)用慣了安卓手機(jī)拭宁,感覺很多安卓...
    果殼里的星辰閱讀 17,404評(píng)論 10 5