摘要:时间年月日星期六说明本文部分内容均来自慕课网。慕课网教学源码学习源码第一章概述课程简介本课程是在之前的初识微信公众号开发课程基础之上的。慕课网课程涵盖前端开发等前沿技术语言,包括基础课程实用案例高级分享三大类型,适合不同阶段的学习人群。
时间:2017年08月12日星期六
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学源码:http://img.mukewang.com/down/...
学习源码:https://github.com/zccodere/s...
本课程是在之前的《初识Java微信公众号开发》课程基础之上的。
之前入门课程主要讲解了
微信公众号及公众号平台的相关概念 编辑模式和开发模式的相关操作
课程内容
消息回复接口 素材管理接口 自定义菜单接口 百度翻译API1-2 微信公众平台测试号
因个人订阅号权限有限,很多高级接口无法使用,所以可以申请测试账号,测试账号对这些接口的权限都放开了。
第二章:素材管理接口 2-1 图文消息复制项目wxdevaccess重命名为wxdevadvanced。其中POM文件如下
4.0.0 com.myimooc wxdevadvanced 0.0.1-SNAPSHOT jar wxdevadvanced http://maven.apache.org org.springframework.boot spring-boot-starter-parent 1.5.1.RELEASE UTF-8 UTF-8 org.springframework.boot spring-boot-starter-web com.alibaba fastjson 1.2.36 org.apache.httpcomponents httpclient commons-codec commons-codec org.apache.maven.plugins maven-compiler-plugin 1.8
由于从此节开始,均属于代码编写,类及代码较多。这里就不全部一一展示了,请到我的github地址查看。完成后的项目结构如下
说明:由于条件限制,此项目代码均没有进行测试,这里只是显示大概开发过程。
接口文档
路径:消息管理》发送消息-被动回复用户消息》回复图文消息 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp14211401832-2 获取access_token(上)
接口文档地址:https://mp.weixin.qq.com/wiki...
编写AccessToken类
package com.myimooc.wxdevadvanced.domain; import java.io.Serializable; /** * 获取 access_token 微信接口响应对象 * @author ZhangCheng on 2017-08-12 * */ public class AccessToken implements Serializable{ private static final long serialVersionUID = 1L; private String token; private int expiresIn; @Override public String toString() { return "AccessToken [token=" + token + ", expiresIn=" + expiresIn + "]"; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } }2-3 获取access_token(下)
编写TokenUtils类
package com.myimooc.wxdevadvanced.util; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSONObject; import com.myimooc.wxdevadvanced.domain.AccessToken; /** * 微信工具类 * @author ZhangCheng on 2017-08-12 * */ public class TokenUtils { private static final String APPID="dsadqawer2124a5wdqw1"; private static final String APPSECRET = "dsadaq875w5edqwd58qwdqwbgthr4t5qa"; private static final String CHARSET_FORMAT = "UTF-8"; private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; /** * 发起GET请求 */ public static JSONObject doGetStr(String url) throws Exception{ HttpClientBuilder builder = HttpClientBuilder.create(); HttpGet httpGet = new HttpGet(url); JSONObject object = null; HttpResponse response = builder.build().execute(httpGet); HttpEntity entity = response.getEntity(); if(null != entity){ String result = EntityUtils.toString(entity,CHARSET_FORMAT); object = JSONObject.parseObject(result); } return object; } /** * 发起POST请求 */ public static JSONObject doPostStr(String url,String outStr)throws Exception{ HttpClientBuilder builder = HttpClientBuilder.create(); JSONObject object = null; HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(outStr,CHARSET_FORMAT)); HttpResponse response = builder.build().execute(httpPost); HttpEntity entity = response.getEntity(); String result = EntityUtils.toString(entity,CHARSET_FORMAT); object = JSONObject.parseObject(result); return object; } /** * 获取access_token */ public static AccessToken getAccessToken(){ AccessToken token = new AccessToken(); String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET); JSONObject json = null; try{ json = doGetStr(url); }catch (Exception e) { } if(null != json && json.containsKey("access_token")){ token.setToken(json.getString("access_token")); token.setExpiresIn(json.getIntValue("expires_in")); } return token; } }2-4 图片消息回复
接口文档
路径:消息管理》发送消息-被动回复用户消息》回复图片消息 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp14211401832-5 音乐消息的回复
接口文档
路径:消息管理》发送消息-被动回复用户消息》回复音乐消息 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543第三章:自定义菜单接口 3-1 自定义菜单(上)
接口文档
路径:自定义菜单》自定义菜单创建接口 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013
代码演示:
1.编写Button类
package com.myimooc.wxdevadvanced.domain.menu; /** * 菜单按钮 * @author ZhangCheng on 2017-08-12 * */ public class Button { private String type; private String name; private Button[] sub_button; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Button[] getSub_button() { return sub_button; } public void setSub_button(Button[] sub_button) { this.sub_button = sub_button; } }
2.编写Menu类
package com.myimooc.wxdevadvanced.domain.menu; /** * 菜单 * @author ZhangCheng on 2017-08-12 * */ public class Menu { private Button[] button; public Button[] getButton() { return button; } public void setButton(Button[] button) { this.button = button; } }
3.编写ClickButton类
package com.myimooc.wxdevadvanced.domain.menu; /** * 点击按钮 * @author ZhangCheng on 2017-08-12 * */ public class ClickButton extends Button{ private String key; public String getKey() { return key; } public void setKey(String key) { this.key = key; } }
4.编写ViewButton类
package com.myimooc.wxdevadvanced.domain.menu; /** * 视图按钮 * @author ZhangCheng on 2017-08-12 * */ public class ViewButton extends Button{ private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }3-2 自定义菜单(下)
代码演示:
1.修改WinxinUtils类
package com.myimooc.wxdevadvanced.util; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.List; import java.util.Map; import com.alibaba.fastjson.JSONObject; import com.myimooc.wxdevadvanced.domain.menu.Button; import com.myimooc.wxdevadvanced.domain.menu.ClickButton; import com.myimooc.wxdevadvanced.domain.menu.Menu; import com.myimooc.wxdevadvanced.domain.menu.ViewButton; import com.myimooc.wxdevadvanced.domain.trans.Data; import com.myimooc.wxdevadvanced.domain.trans.Parts; import com.myimooc.wxdevadvanced.domain.trans.Symbols; import com.myimooc.wxdevadvanced.domain.trans.TransResult; /** * 微信工具类 * @author ZhangCheng on 2017-08-12 * */ public class WeixinUtils { private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; public static String upload(String filePath,String accessToken,String type)throws Exception{ File file = new File(filePath); if(!file.exists() || !file.isFile()){ throw new IOException("文件不存在"); } String url = UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); URL urlObj = new URL(url); // 连接 HttpURLConnection con = (HttpURLConnection)urlObj.openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 设置边界 String BOUNDARY = "-----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); StringBuilder sb = new StringBuilder(); sb.append("--"); sb.append(BOUNDARY); sb.append(" "); sb.append("Content-Disposition;form-data;name="file",filename=""+ file.getName() + "" "); sb.append("Content-Type;application/octet-strean "); byte[] head = sb.toString().getBytes("UTF-8"); // 获得输出流 OutputStream out = new DataOutputStream(con.getOutputStream()); // 输出表头 out.write(head); // 文件正文部分 把文件以流文件的方式 推入到url中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while((bytes = in.read(bufferOut))!= -1){ out.write(bufferOut, 0, bytes); } in.close(); // 结尾部分 byte[] foot = (" --" + BOUNDARY + "-- ").getBytes("utf-8");//定义最后数据分隔线 out.write(foot); out.flush(); out.close(); StringBuffer buffer = new StringBuffer(); BufferedReader reader = null; String result = null; try { //定义BufferedReader输入流来读取URL的响应 reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } if (result == null) { result = buffer.toString(); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } } JSONObject jsonObj = JSONObject.parseObject(result); System.out.println(jsonObj); String typeName = "media_id"; if(!"image".equals(type)){ typeName = type + "_media_id"; } String mediaId = jsonObj.getString(typeName); return mediaId; } /** * 组装菜单 */ public static Menu initMenu(){ Menu menu = new Menu(); ClickButton button11 = new ClickButton(); button11.setName("click菜单"); button11.setType("click"); button11.setKey("11"); ViewButton button21 = new ViewButton(); button21.setName("view菜单"); button21.setType("view"); button21.setUrl("http://www.imooc.com"); ClickButton button31 = new ClickButton(); button31.setName("扫码事件"); button31.setType("scancode_push"); button31.setKey("31"); ClickButton button32 = new ClickButton(); button32.setName("地理位置"); button32.setType("location_select"); button32.setKey("32"); Button button = new Button(); button.setName("菜单"); button.setSub_button(new Button[]{button31,button32}); menu.setButton(new Button[]{button11,button21,button}); return menu; } /** * 创建菜单 */ public static int createMenu(String token,String menu) throws Exception{ int result = 0; String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doPostStr(url, menu); if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 获取菜单 */ public static JSONObject queryMenu(String token) throws Exception{ String url = QUERY_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); return jsonObject; } /** * 移除菜单 */ public static int deleteMenu(String token) throws Exception{ String url = DELETE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); int result = 0; if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 词组翻译 */ public static String translate(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); String errno = jsonObject.getString("errno"); Object obj = jsonObject.get("data"); StringBuffer dst = new StringBuffer(); if("0".equals(errno) && !"[]".equals(obj.toString())){ TransResult transResult = (TransResult) JSONObject.toJavaObject(jsonObject, TransResult.class); Data data = transResult.getData(); Symbols symbols = data.getSymbols()[0]; String phzh = symbols.getPh_zh()==null ? "" : "中文拼音:"+symbols.getPh_zh()+" "; String phen = symbols.getPh_en()==null ? "" : "英式英标:"+symbols.getPh_en()+" "; String pham = symbols.getPh_am()==null ? "" : "美式英标:"+symbols.getPh_am()+" "; dst.append(phzh+phen+pham); Parts[] parts = symbols.getParts(); String pat = null; for(Parts part : parts){ pat = (part.getPart()!=null && !"".equals(part.getPart())) ? "["+part.getPart()+"]" : ""; String[] means = part.getMeans(); dst.append(pat); for(String mean : means){ dst.append(mean+";"); } } }else{ dst.append(translateFull(source)); } return dst.toString(); } /** * 句子翻译 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static String translateFull(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/bmt/translate?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); StringBuffer dst = new StringBuffer(); List3-3 菜单的事件推送
接口文档
路径:自定义菜单》自定义菜单事件推送 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141016
代码演示:
1.修改MessageRest类
package com.myimooc.wxdevadvanced.rest; import java.util.Date; import java.util.Map; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import com.myimooc.wxdevadvanced.domain.EventMessage; import com.myimooc.wxdevadvanced.domain.NewsMessage; import com.myimooc.wxdevadvanced.domain.TextMessage; import com.myimooc.wxdevadvanced.util.MessageUtils; import com.myimooc.wxdevadvanced.util.WeixinUtils; /** * 处理消息请求与响应 * @author ZhangCheng on 2017-08-11 * */ @RestController public class MessageRest { private static final Logger logger = LoggerFactory.getLogger(MessageRest.class); /** * 接收微信服务器发送的POST请求 * @throws Exception */ @PostMapping("textmessage") public Object textmessage(TextMessage msg) throws Exception{ logger.info("请求参数:{}",msg.toString()); // 文本消息 if(Objects.equals(MessageUtils.MESSAGE_TEXT, msg.getMsgType())){ TextMessage textMessage = new TextMessage(); // 关键字 1 if(Objects.equals("1", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.firstMenu()); return textMessage; } // 关键字 2 if(Objects.equals("2", msg.getContent())){ NewsMessage newsMessage = MessageUtils.initNewsMessage(msg.getToUserName(), msg.getFromUserName()); return newsMessage; } // 关键字 3 if(Objects.equals("3", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.threeMenu()); return textMessage; } // 关键字 翻译 if(msg.getContent().startsWith("翻译")){ String word = msg.getContent().replaceAll("^翻译","").trim(); if("".equals(word)){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.threeMenu()); return textMessage; } textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),WeixinUtils.translate(word)); return textMessage; } // 关键字 ?? 调出菜单 if(Objects.equals("?", msg.getContent()) || Objects.equals("?", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return textMessage; } // 非关键字 textMessage.setFromUserName(msg.getToUserName()); textMessage.setToUserName(msg.getFromUserName()); textMessage.setMsgType(MessageUtils.MESSAGE_TEXT); textMessage.setCreateTime(new Date().getTime()+""); textMessage.setContent("您发送的消息是:" + msg.getContent()); return textMessage; } return null; } /** * 接收微信服务器发送的POST请求 */ @PostMapping("eventmessage") public Object eventmessage(Map3-4 菜单查询与删除param){ EventMessage msg = new EventMessage(); BeanUtils.copyProperties(param, msg); // 事件推送 if(Objects.equals(MessageUtils.MESSAGE_EVENT, msg.getMsgType())){ // 关注 if(Objects.equals(MessageUtils.MESSAGE_SUBSCRIBE, msg.getEvent())){ TextMessage text = new TextMessage(); text = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return text; } // 菜单 点击类型 if(Objects.equals(MessageUtils.MESSAGE_CLICK, msg.getEvent())){ TextMessage text = new TextMessage(); text = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return text; } // 菜单 视图类型 if(Objects.equals(MessageUtils.MESSAGE_VIEW, msg.getEvent())){ String url = param.get("EventKey"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),url); } // 菜单 扫码事件 if(Objects.equals(MessageUtils.MESSAGE_SCANCODE, msg.getEvent())){ String key = param.get("EventKey"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),key); } // 菜单 地理位置 if(Objects.equals(MessageUtils.MESSAGE_LOCATION, msg.getEvent())){ String Label = param.get("Label"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),Label); } } return "no message"; } }
接口文档
路径:自定义菜单》自定义菜单查询接口 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014 路径:自定义菜单》自定义菜单删除接口 地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015
代码演示:
1.修改WinxinUtils类
package com.myimooc.wxdevadvanced.util; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.List; import java.util.Map; import com.alibaba.fastjson.JSONObject; import com.myimooc.wxdevadvanced.domain.menu.Button; import com.myimooc.wxdevadvanced.domain.menu.ClickButton; import com.myimooc.wxdevadvanced.domain.menu.Menu; import com.myimooc.wxdevadvanced.domain.menu.ViewButton; import com.myimooc.wxdevadvanced.domain.trans.Data; import com.myimooc.wxdevadvanced.domain.trans.Parts; import com.myimooc.wxdevadvanced.domain.trans.Symbols; import com.myimooc.wxdevadvanced.domain.trans.TransResult; /** * 微信工具类 * @author ZhangCheng on 2017-08-12 * */ public class WeixinUtils { private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; public static String upload(String filePath,String accessToken,String type)throws Exception{ File file = new File(filePath); if(!file.exists() || !file.isFile()){ throw new IOException("文件不存在"); } String url = UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); URL urlObj = new URL(url); // 连接 HttpURLConnection con = (HttpURLConnection)urlObj.openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 设置边界 String BOUNDARY = "-----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); StringBuilder sb = new StringBuilder(); sb.append("--"); sb.append(BOUNDARY); sb.append(" "); sb.append("Content-Disposition;form-data;name="file",filename=""+ file.getName() + "" "); sb.append("Content-Type;application/octet-strean "); byte[] head = sb.toString().getBytes("UTF-8"); // 获得输出流 OutputStream out = new DataOutputStream(con.getOutputStream()); // 输出表头 out.write(head); // 文件正文部分 把文件以流文件的方式 推入到url中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while((bytes = in.read(bufferOut))!= -1){ out.write(bufferOut, 0, bytes); } in.close(); // 结尾部分 byte[] foot = (" --" + BOUNDARY + "-- ").getBytes("utf-8");//定义最后数据分隔线 out.write(foot); out.flush(); out.close(); StringBuffer buffer = new StringBuffer(); BufferedReader reader = null; String result = null; try { //定义BufferedReader输入流来读取URL的响应 reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } if (result == null) { result = buffer.toString(); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } } JSONObject jsonObj = JSONObject.parseObject(result); System.out.println(jsonObj); String typeName = "media_id"; if(!"image".equals(type)){ typeName = type + "_media_id"; } String mediaId = jsonObj.getString(typeName); return mediaId; } /** * 组装菜单 */ public static Menu initMenu(){ Menu menu = new Menu(); ClickButton button11 = new ClickButton(); button11.setName("click菜单"); button11.setType("click"); button11.setKey("11"); ViewButton button21 = new ViewButton(); button21.setName("view菜单"); button21.setType("view"); button21.setUrl("http://www.imooc.com"); ClickButton button31 = new ClickButton(); button31.setName("扫码事件"); button31.setType("scancode_push"); button31.setKey("31"); ClickButton button32 = new ClickButton(); button32.setName("地理位置"); button32.setType("location_select"); button32.setKey("32"); Button button = new Button(); button.setName("菜单"); button.setSub_button(new Button[]{button31,button32}); menu.setButton(new Button[]{button11,button21,button}); return menu; } /** * 创建菜单 */ public static int createMenu(String token,String menu) throws Exception{ int result = 0; String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doPostStr(url, menu); if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 获取菜单 */ public static JSONObject queryMenu(String token) throws Exception{ String url = QUERY_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); return jsonObject; } /** * 移除菜单 */ public static int deleteMenu(String token) throws Exception{ String url = DELETE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); int result = 0; if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 词组翻译 */ public static String translate(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); String errno = jsonObject.getString("errno"); Object obj = jsonObject.get("data"); StringBuffer dst = new StringBuffer(); if("0".equals(errno) && !"[]".equals(obj.toString())){ TransResult transResult = (TransResult) JSONObject.toJavaObject(jsonObject, TransResult.class); Data data = transResult.getData(); Symbols symbols = data.getSymbols()[0]; String phzh = symbols.getPh_zh()==null ? "" : "中文拼音:"+symbols.getPh_zh()+" "; String phen = symbols.getPh_en()==null ? "" : "英式英标:"+symbols.getPh_en()+" "; String pham = symbols.getPh_am()==null ? "" : "美式英标:"+symbols.getPh_am()+" "; dst.append(phzh+phen+pham); Parts[] parts = symbols.getParts(); String pat = null; for(Parts part : parts){ pat = (part.getPart()!=null && !"".equals(part.getPart())) ? "["+part.getPart()+"]" : ""; String[] means = part.getMeans(); dst.append(pat); for(String mean : means){ dst.append(mean+";"); } } }else{ dst.append(translateFull(source)); } return dst.toString(); } /** * 句子翻译 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static String translateFull(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/bmt/translate?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); StringBuffer dst = new StringBuffer(); List第四章:百度翻译API 4-1 百度翻译list = (List ) jsonObject.get("trans_result"); for(Map map : list){ dst.append(map.get("dst")); } return dst.toString(); } }
案例开发
通过百度翻译API来实现词组翻译功能。
百度开放服务平台
地址:http://developer.baidu.com/ms/oauth/ 百度翻译API 地址:http://api.fanyi.baidu.com/api/trans/product/index 百度翻译API文档 地址:http://api.fanyi.baidu.com/api/trans/product/apidoc
代码演示:
1.编写Parts类
package com.myimooc.wxdevadvanced.domain.trans; /** * 百度翻译API * @author ZhangCheng on 2017-08-12 * */ public class Parts { private String part; private String[] means; public String getPart() { return part; } public void setPart(String part) { this.part = part; } public String[] getMeans() { return means; } public void setMeans(String[] means) { this.means = means; } }
2.编写Symbols类
package com.myimooc.wxdevadvanced.domain.trans; /** * 百度翻译API * @author ZhangCheng on 2017-08-12 * */ public class Symbols { private String ph_am; private String ph_en; private String ph_zh; private Parts[] parts; public String getPh_am() { return ph_am; } public void setPh_am(String ph_am) { this.ph_am = ph_am; } public String getPh_en() { return ph_en; } public void setPh_en(String ph_en) { this.ph_en = ph_en; } public String getPh_zh() { return ph_zh; } public void setPh_zh(String ph_zh) { this.ph_zh = ph_zh; } public Parts[] getParts() { return parts; } public void setParts(Parts[] parts) { this.parts = parts; } }
3.编写Data类
package com.myimooc.wxdevadvanced.domain.trans; /** * 百度翻译API * @author ZhangCheng on 2017-08-12 * */ public class Data { private String word_name; private Symbols[] symbols; public String getWord_name() { return word_name; } public void setWord_name(String word_name) { this.word_name = word_name; } public Symbols[] getSymbols() { return symbols; } public void setSymbols(Symbols[] symbols) { this.symbols = symbols; } }
4.编写TransResult类
package com.myimooc.wxdevadvanced.domain.trans; /** * 百度翻译API * @author ZhangCheng on 2017-08-12 * */ public class TransResult { private String from; private String to; private Data data; private String errno; public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public Data getData() { return data; } public void setData(Data data) { this.data = data; } public String getErrno() { return errno; } public void setErrno(String errno) { this.errno = errno; } }
5.修改WeixinUtils类
package com.myimooc.wxdevadvanced.util; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.List; import java.util.Map; import com.alibaba.fastjson.JSONObject; import com.myimooc.wxdevadvanced.domain.menu.Button; import com.myimooc.wxdevadvanced.domain.menu.ClickButton; import com.myimooc.wxdevadvanced.domain.menu.Menu; import com.myimooc.wxdevadvanced.domain.menu.ViewButton; import com.myimooc.wxdevadvanced.domain.trans.Data; import com.myimooc.wxdevadvanced.domain.trans.Parts; import com.myimooc.wxdevadvanced.domain.trans.Symbols; import com.myimooc.wxdevadvanced.domain.trans.TransResult; /** * 微信工具类 * @author ZhangCheng on 2017-08-12 * */ public class WeixinUtils { private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; public static String upload(String filePath,String accessToken,String type)throws Exception{ File file = new File(filePath); if(!file.exists() || !file.isFile()){ throw new IOException("文件不存在"); } String url = UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); URL urlObj = new URL(url); // 连接 HttpURLConnection con = (HttpURLConnection)urlObj.openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 设置边界 String BOUNDARY = "-----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); StringBuilder sb = new StringBuilder(); sb.append("--"); sb.append(BOUNDARY); sb.append(" "); sb.append("Content-Disposition;form-data;name="file",filename=""+ file.getName() + "" "); sb.append("Content-Type;application/octet-strean "); byte[] head = sb.toString().getBytes("UTF-8"); // 获得输出流 OutputStream out = new DataOutputStream(con.getOutputStream()); // 输出表头 out.write(head); // 文件正文部分 把文件以流文件的方式 推入到url中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while((bytes = in.read(bufferOut))!= -1){ out.write(bufferOut, 0, bytes); } in.close(); // 结尾部分 byte[] foot = (" --" + BOUNDARY + "-- ").getBytes("utf-8");//定义最后数据分隔线 out.write(foot); out.flush(); out.close(); StringBuffer buffer = new StringBuffer(); BufferedReader reader = null; String result = null; try { //定义BufferedReader输入流来读取URL的响应 reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } if (result == null) { result = buffer.toString(); } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } } JSONObject jsonObj = JSONObject.parseObject(result); System.out.println(jsonObj); String typeName = "media_id"; if(!"image".equals(type)){ typeName = type + "_media_id"; } String mediaId = jsonObj.getString(typeName); return mediaId; } /** * 组装菜单 */ public static Menu initMenu(){ Menu menu = new Menu(); ClickButton button11 = new ClickButton(); button11.setName("click菜单"); button11.setType("click"); button11.setKey("11"); ViewButton button21 = new ViewButton(); button21.setName("view菜单"); button21.setType("view"); button21.setUrl("http://www.imooc.com"); ClickButton button31 = new ClickButton(); button31.setName("扫码事件"); button31.setType("scancode_push"); button31.setKey("31"); ClickButton button32 = new ClickButton(); button32.setName("地理位置"); button32.setType("location_select"); button32.setKey("32"); Button button = new Button(); button.setName("菜单"); button.setSub_button(new Button[]{button31,button32}); menu.setButton(new Button[]{button11,button21,button}); return menu; } /** * 创建菜单 */ public static int createMenu(String token,String menu) throws Exception{ int result = 0; String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doPostStr(url, menu); if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 获取菜单 */ public static JSONObject queryMenu(String token) throws Exception{ String url = QUERY_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); return jsonObject; } /** * 移除菜单 */ public static int deleteMenu(String token) throws Exception{ String url = DELETE_MENU_URL.replace("ACCESS_TOKEN", token); JSONObject jsonObject = TokenUtils.doGetStr(url); int result = 0; if(jsonObject != null){ result = jsonObject.getIntValue("errcode"); } return result; } /** * 词组翻译 */ public static String translate(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); String errno = jsonObject.getString("errno"); Object obj = jsonObject.get("data"); StringBuffer dst = new StringBuffer(); if("0".equals(errno) && !"[]".equals(obj.toString())){ TransResult transResult = (TransResult) JSONObject.toJavaObject(jsonObject, TransResult.class); Data data = transResult.getData(); Symbols symbols = data.getSymbols()[0]; String phzh = symbols.getPh_zh()==null ? "" : "中文拼音:"+symbols.getPh_zh()+" "; String phen = symbols.getPh_en()==null ? "" : "英式英标:"+symbols.getPh_en()+" "; String pham = symbols.getPh_am()==null ? "" : "美式英标:"+symbols.getPh_am()+" "; dst.append(phzh+phen+pham); Parts[] parts = symbols.getParts(); String pat = null; for(Parts part : parts){ pat = (part.getPart()!=null && !"".equals(part.getPart())) ? "["+part.getPart()+"]" : ""; String[] means = part.getMeans(); dst.append(pat); for(String mean : means){ dst.append(mean+";"); } } }else{ dst.append(translateFull(source)); } return dst.toString(); } /** * 句子翻译 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static String translateFull(String source) throws Exception{ String url = "http://openapi.baidu.com/public/2.0/bmt/translate?client_id=jNg0LPSBe691Il0CG5MwDupw&q=KEYWORD&from=auto&to=auto"; url = url.replace("KEYWORD", URLEncoder.encode(source, "UTF-8")); JSONObject jsonObject = TokenUtils.doGetStr(url); StringBuffer dst = new StringBuffer(); Listlist = (List ) jsonObject.get("trans_result"); for(Map map : list){ dst.append(map.get("dst")); } return dst.toString(); } }
6.修改MessageUtils类
package com.myimooc.wxdevadvanced.util; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.myimooc.wxdevadvanced.domain.Image; import com.myimooc.wxdevadvanced.domain.ImageMessage; import com.myimooc.wxdevadvanced.domain.Music; import com.myimooc.wxdevadvanced.domain.MusicMessage; import com.myimooc.wxdevadvanced.domain.News; import com.myimooc.wxdevadvanced.domain.NewsMessage; import com.myimooc.wxdevadvanced.domain.TextMessage; /** * 消息类型及工具类 * @author ZhangCheng on 2017-08-11 * */ public class MessageUtils { public static final String MESSAGE_TEXT = "text"; public static final String MESSAGE_NEWS = "news"; public static final String MESSAGE_IMAGE = "image"; public static final String MESSAGE_VOICE = "voice"; public static final String MESSAGE_MUSIC = "music"; public static final String MESSAGE_VIDEO = "video"; public static final String MESSAGE_LINK = "link"; public static final String MESSAGE_LOCATION = "location"; public static final String MESSAGE_EVENT = "event"; public static final String MESSAGE_SUBSCRIBE = "subscribe"; public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe"; public static final String MESSAGE_CLICK = "CLICK"; public static final String MESSAGE_VIEW = "VIEW"; public static final String MESSAGE_SCANCODE = "scancode_push"; public static TextMessage initText(String toUserName,String fromUserName,String content){ TextMessage text = new TextMessage(); text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(MessageUtils.MESSAGE_TEXT); text.setCreateTime(new Date().getTime()+""); text.setContent(content); return text; } /** * 主菜单 */ public static String menuText(){ StringBuffer sb = new StringBuffer(); sb.append("欢迎您的关注,请按照菜单提升进行操作: "); sb.append("1、课程介绍 "); sb.append("2、慕课网介绍 "); sb.append("3、词组翻译 "); sb.append("回复?显示主菜单。"); return sb.toString(); } public static String firstMenu(){ StringBuffer sb = new StringBuffer(); sb.append("本套课程介绍微信公众号开发,主要涉及公众号介绍、编辑模式介绍、开发模式介绍等。"); return sb.toString(); } public static String secondMenu(){ StringBuffer sb = new StringBuffer(); sb.append("慕课网是垂直的互联网IT技能免费学习网站。以独家视频教程、在线编程工具、学习计划、" + "问答社区为核心特色。在这里,你可以找到最好的互联网技术牛人,也可以通过免费的在线公" + "开视频课程学习国内领先的互联网IT技术。" + "慕课网课程涵盖前端开发、PHP、Html5、Android、iOS、Swift等IT前沿技术语言," + "包括基础课程、实用案例、高级分享三大类型,适合不同阶段的学习人群。" + "以纯干货、短视频的形式为平台特点,为在校学生、职场白领提供了一个迅速提升技能、共同分享进步的学习平台。"); return sb.toString(); } public static String threeMenu(){ StringBuffer sb = new StringBuffer(); sb.append("词组翻译使用指南 "); sb.append("使用示例: "); sb.append("翻译足球: "); sb.append("翻译中国足球 "); sb.append("翻译football "); sb.append("回复?显示主菜单。"); return sb.toString(); } /** * 图文消息的组装 */ public static NewsMessage initNewsMessage(String toUserNmae,String fromUserName){ ListnewsList = new ArrayList (); NewsMessage newsMessage = new NewsMessage(); News news = new News(); news.setTitle("慕课网介绍"); news.setDescription("慕课网是垂直的互联网IT技能免费学习网站。以独家视频教程、在线编程工具、学习计划、" + "问答社区为核心特色。在这里,你可以找到最好的互联网技术牛人,也可以通过免费的在线公" + "开视频课程学习国内领先的互联网IT技术。" + "慕课网课程涵盖前端开发、PHP、Html5、Android、iOS、Swift等IT前沿技术语言," + "包括基础课程、实用案例、高级分享三大类型,适合不同阶段的学习人群。" + "以纯干货、短视频的形式为平台特点,为在校学生、职场白领提供了一个迅速提升技能、共同分享进步的学习平台。"); news.setPicUrl("http://imooc.jpg"); news.setUrl("www.imooc.com"); newsList.add(news); newsMessage.setToUserName(fromUserName); newsMessage.setFromUserName(toUserNmae); newsMessage.setCreateTime(new Date().getTime()+""); newsMessage.setMsgType(MESSAGE_NEWS); newsMessage.setArticles(newsList); newsMessage.setArticleCount(newsList.size()); return newsMessage; } /** * 图片消息组装 */ public static ImageMessage initImageMessage(String toUserName,String fromUserName){ Image image = new Image(); image.setMediaId("JTH8vBl0zDRlrrn2bBnMleySuHjVbMhyAo0U2x7kQyd1ciydhhsVPONbnRrKGp8m"); ImageMessage imageMessage = new ImageMessage(); imageMessage.setFromUserName(toUserName); imageMessage.setToUserName(fromUserName); imageMessage.setMsgType(MESSAGE_IMAGE); imageMessage.setCreateTime(new Date().getTime()+""); imageMessage.setImage(image); return imageMessage; } /** * 组装音乐消息 * @param toUserName * @param fromUserName * @return */ public static MusicMessage initMusicMessage(String toUserName,String fromUserName){ Music music = new Music(); music.setThumbMediaId("WsHCQr1ftJQwmGUGhCP8gZ13a77XVg5Ah_uHPHVEAQuRE5FEjn-DsZJzFZqZFeFk"); music.setTitle("see you again"); music.setDescription("速7片尾曲"); music.setMusicUrl("http://zapper.tunnel.mobi/Weixin/resource/See You Again.mp3"); music.setHQMusicUrl("http://zapper.tunnel.mobi/Weixin/resource/See You Again.mp3"); MusicMessage musicMessage = new MusicMessage(); musicMessage.setFromUserName(toUserName); musicMessage.setToUserName(fromUserName); musicMessage.setMsgType(MESSAGE_MUSIC); musicMessage.setCreateTime(new Date().getTime()+""); musicMessage.setMusic(music); return musicMessage; } }
7.修改MessageRest类
package com.myimooc.wxdevadvanced.rest; import java.util.Date; import java.util.Map; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import com.myimooc.wxdevadvanced.domain.EventMessage; import com.myimooc.wxdevadvanced.domain.NewsMessage; import com.myimooc.wxdevadvanced.domain.TextMessage; import com.myimooc.wxdevadvanced.util.MessageUtils; import com.myimooc.wxdevadvanced.util.WeixinUtils; /** * 处理消息请求与响应 * @author ZhangCheng on 2017-08-11 * */ @RestController public class MessageRest { private static final Logger logger = LoggerFactory.getLogger(MessageRest.class); /** * 接收微信服务器发送的POST请求 * @throws Exception */ @PostMapping("textmessage") public Object textmessage(TextMessage msg) throws Exception{ logger.info("请求参数:{}",msg.toString()); // 文本消息 if(Objects.equals(MessageUtils.MESSAGE_TEXT, msg.getMsgType())){ TextMessage textMessage = new TextMessage(); // 关键字 1 if(Objects.equals("1", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.firstMenu()); return textMessage; } // 关键字 2 if(Objects.equals("2", msg.getContent())){ NewsMessage newsMessage = MessageUtils.initNewsMessage(msg.getToUserName(), msg.getFromUserName()); return newsMessage; } // 关键字 3 if(Objects.equals("3", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.threeMenu()); return textMessage; } // 关键字 翻译 if(msg.getContent().startsWith("翻译")){ String word = msg.getContent().replaceAll("^翻译","").trim(); if("".equals(word)){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.threeMenu()); return textMessage; } textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),WeixinUtils.translate(word)); return textMessage; } // 关键字 ?? 调出菜单 if(Objects.equals("?", msg.getContent()) || Objects.equals("?", msg.getContent())){ textMessage = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return textMessage; } // 非关键字 textMessage.setFromUserName(msg.getToUserName()); textMessage.setToUserName(msg.getFromUserName()); textMessage.setMsgType(MessageUtils.MESSAGE_TEXT); textMessage.setCreateTime(new Date().getTime()+""); textMessage.setContent("您发送的消息是:" + msg.getContent()); return textMessage; } return null; } /** * 接收微信服务器发送的POST请求 */ @PostMapping("eventmessage") public Object eventmessage(Mapparam){ EventMessage msg = new EventMessage(); BeanUtils.copyProperties(param, msg); // 事件推送 if(Objects.equals(MessageUtils.MESSAGE_EVENT, msg.getMsgType())){ // 关注 if(Objects.equals(MessageUtils.MESSAGE_SUBSCRIBE, msg.getEvent())){ TextMessage text = new TextMessage(); text = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return text; } // 菜单 点击类型 if(Objects.equals(MessageUtils.MESSAGE_CLICK, msg.getEvent())){ TextMessage text = new TextMessage(); text = MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(), MessageUtils.menuText()); return text; } // 菜单 视图类型 if(Objects.equals(MessageUtils.MESSAGE_VIEW, msg.getEvent())){ String url = param.get("EventKey"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),url); } // 菜单 扫码事件 if(Objects.equals(MessageUtils.MESSAGE_SCANCODE, msg.getEvent())){ String key = param.get("EventKey"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),key); } // 菜单 地理位置 if(Objects.equals(MessageUtils.MESSAGE_LOCATION, msg.getEvent())){ String Label = param.get("Label"); return MessageUtils.initText(msg.getToUserName(), msg.getFromUserName(),Label); } } return "no message"; } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67600.html
摘要:时间年月日星期五说明本文部分内容均来自慕课网。本套课程介绍微信公众号开发,主要涉及公众号介绍编辑模式介绍开发模式介绍等。慕课网是垂直的互联网技能免费学习网站。 时间:2017年08月11日星期五说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:https://github.com/zccodere/s...学习源码:https://github...
摘要:时间年月日星期六说明本文部分内容均来自慕课网。第六章公众号与开发平台关联公众号与开放平台关联情景说明当使用端进行微信授权登录时,得到的和公众号授权登录时得到的不一样。 时间:2017年08月12日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:课程介绍...
摘要:因为某些原因,不方便在这里直接发送百度链接,关注我的微信公众号面试通关手册回复资源分享第一波即可领取。然后大家还有什么问题的话,可以在我的微信公众号后台面试通关手册给我说或者加我微信,我会根据自己的学习经验给了说一下自己的看法。 这是一篇针对Java初学者,或者说在Java学习路线上出了一些问题(不知道该学什么、不知道整体的学习路线是什么样的) 第一步:Java基础(一个月左右) 推荐...
摘要:编程思想第版这本书要常读,初学者可以快速概览,中等程序员可以深入看看,老鸟还可以用之回顾的体系。以下视频整理自慕课网工程师路径相关免费课程。 我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailclimb/Java-Guide 笔者建议初学者学习Java的方式:看书+视频+实践(初...
摘要:时间年月日星期日说明本文部分内容均来自慕课网。慕课网教学示例源码个人学习源码第一章课程介绍课程介绍本课程紧接着小时学会课程,请先看入门课。异常返回通知在连接点抛出异常后执行。 时间:2017年3月19日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学示例源码:https://github.com/zccodere/s...个人学习源码:htt...
阅读 25604·2021-09-29 09:41
阅读 4672·2021-09-10 11:20
阅读 1880·2021-09-09 09:32
阅读 1861·2019-08-30 15:44
阅读 3172·2019-08-29 17:13
阅读 2782·2019-08-29 14:14
阅读 2005·2019-08-29 14:11
阅读 3207·2019-08-29 12:36