//////////////////////////// 注意: 此博客是个人工作笔记 非独立demo//////////////////////////////////

........................................................................................................................................................................................................................

业务介绍:

          最近搞的新系统有一个传单发放的功能,因为要赶着新系统先上线使用,所以老大说先使用老系统的代码,就是先写个接口调用支撑一下 下面是新系统调用老系统接口的方法
URL json(gson) html(jsoup)文件 及 IO流的使用

下面首先是http远程调用的方法  先称之为工具类

  1. public String postTelentService(String urlStr,String urlParameter) throws IOException{
  2. //java.net.URL 主要用于基于Internet的网络通信编程
  3. URL url = new URL(urlStr);//URL的构造方法
  4. //参数是值 请求的URL连接的地址(就是url) 字符串类型的
  5. HttpURLConnection urlcon = (HttpURLConnection)url.openConnection();//打开这个url连接 此方法声明抛出IO异常 返回值是URLConnection类型的 连接对象
  6. //我们强制转型为他的一个实现类:HttpURLConnection
  7. urlcon.setDoOutput(true);//设置是否向connection输出
  8. //因为我们是个post类型的请求 参数要放在http正文当中,所以我们要设置成true
  9. urlcon.setDoInput(true);// read from the connection.Defult is true
  10. urlcon.setRequestMethod("POST");//设置http请求的方法 默认是GET方式
  11.  
  12. urlcon.setUseCaches(false);//POST请求不能使用缓存
  13. urlcon.setInstanceFollowRedirects(true);//前者设置所有的http连接是否自动处理重定向
  14.  
  15. urlcon.setRequestProperty("Content-Type","application/x-www-form-urlencoded");//配置本次连接的Content-type,配置为application/x-www-form-urlencoded的意思是 正文是urlencoded编码过的form参数 下面我们可以看到我们对正文内容使用URLEncoder.encode 进行编码
  16. /*google大神解释:
  17. * 这个是告诉服务器 你的客户端的配置/需求
  18. 比如说你要取某个文件的多少字节到多少字节就通过这个东西告诉服务器
  19. 你的客户端支持压缩,也可以告诉服务器 服务器会压缩传输
  20. 你的客户端支持什么编码 也可以告诉服务器 服务器会尽量按照你的编码传递数据
  21. 还有比如你的客户端是什么类型,IE,FIrefox之类,有的服务器会按照你的客户端类型给你传送文本
  22. 你啥都不告诉 服务器就按缺省配置传递内容给你的客户端
  23. */
  24. /** 还有注意点:
  25. * 1 连接,从openConnection()至此的相关配置设定 必须在connect()之前完成!
  26. * 2 connection.getOutputStream会隐含的进行connect()方法
  27. */
  28. urlcon.connect();//配置完后 (规定好格式的传输对象? 打开对象的连接?)
  29.  
  30. DataOutputStream out = new DataOutputStream(urlcon.getOutputStream());//获取 当前连接对象的输出流 然后包装成数据流
  31.  
  32. String content = urlParameter;//post方法的http请求正文起始跟 url中?后的参数字符串一致
  33. out.writeBytes(content);//byte=8bit 以bate的形式讲内容写到向外的流内
  34. out.flush();//强行刷入内存
  35. out.close();//关闭输出流
  36.  
  37. InputStream is = urlcon.getInputStream();//为了获取结果的 输入流 原始流
  38. BufferedReader buffer = new BufferedReader(new InputStreamReader(is));//包装成字符输出流 再转换成字节输出流
  39. StringBuffer bs = new StringBuffer();
  40. String l = null;
  41. while((l=buffer.readLine())!=null){ //读取一行 如果不为空则 in √
  42. bs.append(l).append("/n");//换行
  43. }
  44. String str1 = bs.toString();// 将Stringbuffer转换成字符串
  45. str1 = new String(str1.getBytes("GBK"),"UTF-8");//gbk转成utf-8
  46. String str2 = str1.subString(0,str1.length()-2);//获取字符串 截取后面最后一位
  47. return str2;
  48. }

好了  方法封装完毕  io流有些日子没写过  生疏了不少  下面是调用方法的时候的代码 简单的写写

  1. String assUserIds = RequestUtil.getStringParam(request, "assUserIds");
  2. String urlStr="http://"+ Config.getMkpUrl()+"/marketa/remotePassFlyers.do"; // 调用其他系统的方法 基于http调用 路径配置
  3. // urlStr+="?userId="+userId+"&maId="+maId+"&flyerId="+flyerId+"&userIds="+userIds+"&assUserIds="+assUserIds;
  4. String urlParameter="userId="+userId+"&maId="+maId+"&flyerId="+flyerId+"&userIds="+userIds+"&assUserIds="+assUserIds;
  5. // userId=8665&maId=1015&flyerId=38273&userIds=8665,8687,8688
  6. String result = null;
  7. inviteAllUsers(request);
  8. try {
  9. result = this.postTelentService(urlStr,urlParameter);//路径和参数传递 请求
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. }

//---------------------------------------------------------------------------------------------------------------------------------------------------------

好了新系统的 调用方法撰写完毕

//=============================================================================================//
新系统用的springMVC spring MyBatis
老系统相信通过那个url路径就能看出以前用的是struts
又因为老系统已经上线了几年了 老员工告诉我尽量不要动他们写好的代码 直接调用或者自己重写一个 到时候更新.class文件就行了
//============================================================================================//
分析业务逻辑 及 需求分析
涉及到两个表 第一个表 d_flyer是传单对应表 里面存放的有 传单的id 复制的谁的模板 更新时间 所属人和活动 等等
d_flyer_detail 里面存放了 对应的个人内容==
老系统传单模块分析: 首先由 主管 创建一个活动 然后为此活动创建一个相应的推广的传单
传单: 一个静态的html文件 里面有需要展示的内容 :
1 名片 ./

-------------------------------------
2 反馈表 用于采集有意向的用户的信息
当 主管 创建完成后 传单的名片(如果此电子传单有名片)内部是主管的相关的信息 然后 主管 邀请 组织内部人员参加此活动 并为人员下发此传单 因为主管点击邀请后 被邀请人需要登录账号 进入软件后接受邀请 然后主管才能给其发送传单 而且这样太繁琐

因为下发传单也涉及到了传单的复制(即 主管传单的静态html文件要复制一份给当前的用户) 他复制的地址一直是在老系统中 所以说只能让老系统提供给新系统一个调用接口 来进行调用

新系统对应需求是: 勾选相应的人员 给他们发送传单 跳过了邀请接受的繁琐

即:批量发送功能

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

由url的http请求内容(即参数)我们看出 调用老系统的参数有:
"userId=" userId //当前账号的id
"&maId=" maId //当前活动的id
"&flyerId=" flyerId //当前活动绑定传单的id
"&userIds=" userIds //被邀请人的id s 多个
"&assUserIds=" assUserIds //其他被邀请人的id s
//
//下面是老系统写的接口:
//刚才已经说了 老系统是拿struts spring 和JdbcTemplate写的
//本人并不知道jdbcTemplate的原理 但是感觉应该就是一个数据库框架 没有时间研究它了 同事也说已经过时很久了 不是主流了 只能先放着
//其他的不说了 struts是action了 接口如下:

  1. public class Action{
  2. /**
  3. * 这个方法是给另一个系统调用的
  4. * 传递过来的参数分析: 业务分析:
  5. * 1 userId 当前登录的用户的id 有一个单独的人(主管)专门做传单 传单完成后进行下发
  6. * 所以说他就是在做传单的模板
  7. * 2 maId 指的是当前活动的id 下发传单实际上是对现有(某个活动某个用户)模板传单进行复制
  8. * 在表d_flyer中
  9. * 进行了赋值 穿但是的user_id字段赋以接受传单人的id
  10. * 3 flyerId 指的是传单id 它现在写的应该是错误的(但是有个逻辑就是 一个活动只有一个原本的传单模板)
  11. * 4 userIds 指的是下发到的目标用户 本来是个数组 后来传过来的时候是用了 toString()方法
  12. * 5 assUserIds 已经废弃
  13. * 远程下发传单
  14. * @return
  15. */
  16. public String remotePassFlyers(){
  17. //远程调用的参数示例为: userId=8665&maId=1015&flyerId=38273&userIds=8665,8687,8688&assUserIds=
  18. System.out.println("This is in:Action.remotePassFlyers() ; \n " +
  19. "---wunian7yulian testing...-----The var is: null , And The value is: " + "--flag1--" + " \t ---------");
  20. Integer userId = Integer.parseInt(this.getRequest().getParameter("userId"));
  21. Integer maId = Integer.parseInt(this.getRequest().getParameter("maId"));
  22. Integer flyerId = Integer.parseInt(this.getRequest().getParameter("flyerId"));
  23.  
  24. String userIds = this.getRequest().getParameter("userIds");
  25. String assUserIds = this.getRequest().getParameter("assUserIds");
  26.  
  27. if(isBlank(maId) || isBlank(flyerId)){ //如果没有活动参数或者传单参数
  28. return "ERROR INPUT PARAM";
  29. }
  30. //................................................主要方法.......................
  31. this.getMarketaService().passFlyerToUsers(userId, maId, flyerId, userIds, assUserIds);//spring注入的service层实例对象
  32. return SUCCESS;
  33. // return maId+";"+flyerId+";"+userIds+";"+assUserIds;
  34. }
  35.  
  36. private boolean isBlank(Integer i){
  37. boolean flag = true;
  38. if(null!=i && 0!=i){
  39. flag = false;
  40. }
  41. return flag;
  42. }
  43. }
  44. //=======================================================================================================

下面是service层的代码  有详细清楚的的注释:

  1. //==============================================================service层=====================================================================
  2. public class MarketaService extends BaseService{
  3. /**
  4. * =====================================远程action层调用此方法发送传单==================================================================
  5. */
  6. ///远程调用的参数为: userId=8665&maId=1015&flyerId=38273&userIds=8665,8687,8688&assUserIds=
  7. /** 服务层对接控制层 调用数据层
  8. * 对接 action中的 远程下发传单 方法 remotePassFlyers ()
  9. * 下发活动传单
  10. * @param userId 当前用户的id
  11. * @param maId 当前活动的id
  12. * @param flyerId 传单的id
  13. * @param userIds 目标用户的id
  14. * @param assUserIds --null
  15. * @return ProcResult --> 专门用于存放(封装)返回值的工具bean类
  16. */
  17. public ProcResult passFlyerToUsers(Integer userId, Integer maId, Integer flyerId, String userIds, String assUserIds){
  18. /**辅助方法清单 方法一*/
  19. List<Map<String, Object>> users = getInvitedUserInfos(maId, flyerId, userIds, assUserIds);//获取用户的信息对应传单id 没有传单id的为null 就是指没有收到过传单
  20. //里面都有 --- 用户id 和创建用户组织的id 和 传单id
  21. if(null != users && !users.isEmpty()){//非空才进去 (只要userIds有值就行)
  22. //声明两个list集合 分别用于存放:
  23. List<Integer> hasSharedList = new ArrayList<Integer>();//已经被分享了的成员
  24. List<Integer> notSharedList = new ArrayList<Integer>();//还没有被分享的成员 id的集合
  25.  
  26. for(int i=0; i<users.size(); i++){
  27. Map<String, Object> user = users.get(i); //每个用户遍历出来 取出来的个体对象都是一个map
  28. //map的entity是[列名:值]的方式
  29. // String : Object
  30. //例{"user_id":8875,"id":9999}
  31. Integer inviteUserId = Integer.parseInt(user.get("user_id").toString()) ;//用户的id
  32. boolean isShared = user.get("id")!=null;// 传单id 传单id不为空则说明已经有了 就是已经复制了模板
  33. if(isShared){ //已经分享了的 用户id ~s
  34. hasSharedList.add(inviteUserId);
  35. } else { //还没有传单的 用户的id ~s
  36. notSharedList.add(inviteUserId);//没有分享的用户的id
  37. }
  38. }
  39. System.out.println("This is in:com.chanjet.mkp.marketa.MarketaService.passFlyerToUsers() ; \n " +
  40. "---wunian testing...-----The var is: 已经分享的:没有分享的 , And The value is: " + hasSharedList.size() +"//"+ notSharedList.size() + " \t ---------");
  41. //上面是对 已派发过的和未派发过的进行了 !!!分类!!! 整理到了两个list里面
  42. /* ***************************************************************华丽丽的分割线***************************************************/
  43. /* ***************************************************************华丽丽的分割线***************************************************/
  44. /* ***************************************************************华丽丽的分割线***************************************************/
  45.  
  46. //对所有已经派发过的批量修改
  47. if(!hasSharedList.isEmpty()){//已经派发的 hasSharedList 数组里面保存的是 已经有的传单的user_id ~s
  48. /**辅助方法清单:方法二*/
  49. List<Map<String, Object>> sharedFlyers = getSharedFlyerDetaiInfo(maId, flyerId);// 所有在活动下父传单为模板传单的 子传单的详细信息 询已经共享的传单的user_id
  50. Integer[] sharedFlyerArray = new Integer[sharedFlyers.size()];//查看一共有多少个已经派送了的传单 以多少作为长度 声明一个Integer类型的数组
  51. for(int i=0; i<sharedFlyers.size(); i++){ //循环遍历出相关的子传单的详细信息来
  52. Map<String, Object> flyer = sharedFlyers.get(i);
  53. Integer sFlyerId = (Integer) flyer.get("flyer_id");//传单的id
  54. sharedFlyerArray[i] = sFlyerId;//这样把现有的传单的id 放在一个数组里面 叫做sharedFlyerArray
  55. }
  56. /**辅助方法清单:方法三*/
  57. String sharedUserIds = castArrayToString(hasSharedList.toArray());//把已经分享的用户(list集合)弄出来 转换成数组 变成字符串 被分享的用户的id ~s
  58. String sharedFlyerIds = castArrayToString(sharedFlyerArray); // 把现有的传单的id的数组转换成一个字符串
  59. // 对应的传单的id ~s
  60.  
  61. /**辅助方法清单:方法四*/
  62. String updateFlyerSql = getPassFlyerSql(1).replace("{user_ids}", sharedUserIds); //肯定是sql的in用
  63. //更新了 已经被分享的用户的id的所有需要更新的相关信息的sql语句
  64. //
  65. String updateDlyerDetailSql = getPassFlyerSql(3).replace("{flyer_ids}", sharedFlyerIds);// same
  66. //更新 已经被分享用户的传单的 详细表(子表)的相关详细信息的sql语句
  67.  
  68. Object[] flyerParam = new Object[]{flyerId, maId, flyerId};
  69. Object[] flyerDetailParam = new Object[]{flyerId};
  70. this.getDao().update(updateFlyerSql, flyerParam);//更新 d_flyer表
  71. this.getDao().update(updateDlyerDetailSql, flyerDetailParam); // 更新了他的子表
  72. }
  73. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  74. //对所有未发送过的批量添加 没有什么传单的
  75. if(!notSharedList.isEmpty()){ // 没有发送过的 就是d_flyer 所属人 缺少穿过来的那些 的
  76. /**辅助方法清单:方法三*/
  77. String notSharedUserIds = castArrayToString(notSharedList.toArray());
  78. /**辅助方法清单:方法四*/
  79. String addFlyerSql = getPassFlyerSql(5);// 多行插入 d_flyer 语句(复制传单语句)
  80. addFlyerSql = addFlyerSql.replace("{parent_id}",flyerId+"").replace("{user_ids}", notSharedUserIds);
  81. //填充数据 批量复制传单语句 最后一个parent_id字段要写上模板(父传单的id值 )的id值
  82. Object[] addFlyerParams = new Object[]{flyerId,userId};
  83. this.getDao().update(addFlyerSql, addFlyerParams);
  84. /**辅助方法清单:方法四*/
  85. List<Map<String, Object>> newAddFlyerList = getSharedFlyerInfoByUserIds(maId, flyerId, castArrayToString(notSharedList.toArray()));//查询出刚刚分发出的传单的
  86. Object[] newAddFlyerIds = new Object[newAddFlyerList.size()]; //新增加的传单个数 声明一个数组
  87. for(int i=0; i<newAddFlyerList.size(); i++){ //
  88. Map<String, Object> newF = newAddFlyerList.get(i);
  89. newAddFlyerIds[i] = newF.get("flyer_id"); //新传单的id存放到数组里面 获得传单id 并放到数组中
  90. }
  91. /**辅助方法清单:方法三*/
  92. String newAddFIds = castArrayToString(newAddFlyerIds); //数组转换成字符串 去掉了空格
  93. /**辅助方法清单:方法四*/
  94. String addFlyerDetailSql = getPassFlyerSql(4).replace("{flyer_ids}", newAddFIds);// 插入对应的子表的数据
  95. Object[] addFlyerDetailParams = new Object[]{flyerId};
  96. this.getDao().update(addFlyerDetailSql, addFlyerDetailParams);//因为关联到了子表
  97. }
  98. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~相对应的数据库的所有表的查询 更新操作结束!!!~~~~~~~~~~~
  99. //获取 所有属于此活动的 父传单id为flyerId的 所有复制版本员工传单
  100. // 返回数据字段有:
  101. // 用户的id 传单id 用户对应组织id 传单详细信息表的内容 发布后的内容
  102. // 邮箱 电话 qq 微信 名称 职位
  103. /**辅助方法清单:方法二*/
  104. List<Map<String, Object>> allSharedFlyers = getSharedFlyerDetaiInfo(maId, flyerId);//插入完成后再次重新获取所有相关的传单
  105. //重新上传html文件
  106. try {
  107. /**辅助方法清单:方法六*/
  108. refreshNameCard(allSharedFlyers); //更新传单名片信息(数据库中的content字段的更新)
  109. //重新生成静态html页面
  110. Integer orgId=0;
  111. /**辅助方法清单:方法十一 */
  112. uploadShareFlyerHtmlFile(maId, flyerId, userId, orgId, allSharedFlyers);
  113. } catch (Exception e) {
  114. e.printStackTrace();
  115. }
  116. }
  117. return ProcResult.success();
  118. }
  119.  
  120. /**
  121. * =====================================辅助方法清单:方法一==================================================================
  122. * 返回值为 此活动 模板传单是相应传单模板的 未删除 的且user_id 在参数里面的所有满足条件的 用户id 传单id
  123. * 即 在此活动被邀请 且有传单的所有人
  124. * 传入的userIds作为了左表!!!!! (9876有无对应的fid都会有一条对应 生成 9876 null)
  125. */
  126. private List<Map<String, Object>> getInvitedUserInfos(Integer maId, Integer flyerId, String userIds, String assUserIds){
  127. String sql = "select " +
  128. " u.user_id as user_id,f.id as id " + //用户id 和创建用户组织的id 和 传单id
  129. " from m_user u " +
  130. " left join d_flyer f " +
  131. " on u.user_id = f.user_id " +
  132. " and f.ma_id=? " + // 所属活动限定
  133. " and f.parent_id=? " + //这填充的是 传单模板(父传单)的id值 这样就又是一个小型的无线分类 知道了模板的来源
  134. " and f.deleted = 0" + // 删除 ? 否限定
  135. " where (u.user_id in ({userIds}) ) and del = 0 ";// 用户限定 穿过来的用户
  136. /**
  137. * select u.user_id as user_id,f.id as id
  138. * from m_user u
  139. * left join d_flyer f on u.user_id = f.user_id And f.ma_id =? and parent_id=? and f.deleted =0
  140. * where (u.user_id in ({userIds}) ) and del =0;
  141. 由此看出是preparedstatement in 为什么用替换? 我试了一下用? 出错了
  142. */
  143. sql = sql.replace("{userIds}",userIds);//参数填充
  144. Object[] params = new Object[]{maId, flyerId}; //准备参数
  145. System.out.println(sql + "=========>");
  146. System.out.println(
  147. "==========\n"+"maId:"+maId +"\n flyerId:"+flyerId +"\n userIds:" + userIds);
  148. List<Map<String, Object>> list = this.getDao().query(sql, params, null);//
  149. System.out.println("查询列表长度为: "+ list.size() +"==="+list+ " \t ---------");
  150. return list;
  151. }
  152. //==================================================================================================
  153.  
  154. /**
  155. * =====================================辅助方法清单:方法二==================================================================
  156. */
  157. private List<Map<String, Object>> getSharedFlyerDetaiInfo(Integer maId, Integer parentFlyerId){
  158. List<Map<String, Object>> list = null;
  159. String sql = "SELECT t.user_id, t.id AS flyer_id, t.orgid, d.content, d.updated_content," +
  160. " m.email, m.mobile, m.phone, m.qq, m.weixin, m.user_name as realname ,mou.position AS job " +
  161. " FROM d_flyer t" +
  162. " left join d_flyer_detail d on t.id=d.flyer_id" +
  163. " left join m_user m on t.user_id = m.user_id"+
  164. " left join m_org_user mou on mou.user_id = m.user_id and mou.dept_id !=0" +
  165. " WHERE t.parent_id = ? AND t.ma_id = ? AND t.deleted = 0";
  166. /*
  167. SELECT ? FROM d_flyer t
  168. left join d_flyer_detail d on t.id=d.flyer_id
  169. left join m_user m on t.user_id = m.user_id
  170. left join m_org_user mou on mou.user_id = m.user_id and mou.dept_id !=0
  171. WHERE t.parent_id = ? AND t.ma_id = ? AND t.deleted = 0
  172. */
  173. list = this.getDao().query(sql, new Object[]{parentFlyerId, maId}, null);
  174. return list;
  175. }
  176. /**
  177. * =====================================辅助方法清单:方法三==================================================================
  178. */
  179. /**
  180. * 把数组拼接成以","隔开的字符串
  181. * @param array
  182. * @return
  183. */
  184. private String castArrayToString(Object[] array){
  185. String str = "";
  186. if(null==array){
  187. return str;
  188. }
  189. switch (array.length){
  190. case 1:
  191. str = array[0].toString();
  192. break;
  193. default:
  194. for(int i=0; i<array.length; i++){
  195. if(i==array.length-1){
  196. str += array[array.length-1].toString();
  197. break;
  198. }
  199. str += array[i].toString() + ",";
  200. }
  201. }
  202. return str;
  203. }
  204.  
  205. /**
  206. * =====================================辅助方法清单:方法四==================================================================
  207. */
  208. private String getPassFlyerSql(Integer type){
  209. String sql = "";
  210. switch (type) {
  211. case 1: // updateFlyer
  212. sql = "UPDATE d_flyer t1, d_flyer t2 SET t1.title = t2.title," +
  213. " t1.status = t2.status," +
  214. " t1.create_time = NOW()," +
  215. " t1.notice = t2.notice," +
  216. " t1.template = t2.template," +
  217. " t1.update_time = NOW()," +
  218. " t1.description = t2.description," +
  219. " t1.beau_sel = t2.beau_sel, " +
  220. " t1.refer_count = t2.refer_count," +
  221. " t1.refer_id = t2.refer_id," +
  222. " t1.isdraw = t2.isdraw," +
  223. " t1.iscopy = t2.iscopy," +
  224. " t1.is_marketa_enjoy = 0," +
  225. " t1.showTitle = t2.showTitle," +
  226. " t1.searchKeyword = t2.searchKeyword," +
  227. " t1.music = t2.music," +
  228. " t1.classify_id = t2.classify_id," +
  229. " t1.template_status = t2.template_status," +
  230. " t1.option_id = t2.option_id," +
  231. " t1.approvedBy = t2.approvedBy," +
  232. " t1.deleteReason = t2.deleteReason" +
  233. " WHERE t1.user_id IN ({user_ids}) AND t1.parent_id= ? AND t1.ma_id= ? AND t2.id=?";
  234. break;
  235. case 2:// insertFlyer
  236. sql = "INSERT INTO d_flyer(title,status,create_time,notice,template,user_id,update_time,description,deleted,orgid,hit,notice_days,visitor_count,feedback_count,ishot,version,is_edit,is_add,beau_sel,ma_id,isorg,refer_count,refer_id,isdraw,iscopy,is_marketa_enjoy,showTitle,searchKeyword,music,classify_id,template_status,option_id,approvedBy,deleteReason,parent_id)" +
  237. " SELECT t1.title,t1.status,NOW(),t1.notice,t1.template,t2.invite_user_id,NOW(),t1.description,0,t2.adscription_org,0,t1.notice_days,0,0,t1.ishot,2.00,t1.is_edit,t1.is_add,t1.beau_sel,t1.ma_id,t1.isorg,t1.refer_count,t1.refer_id,t1.isdraw,t1.iscopy,0,t1.showTitle,t1.searchKeyword,t1.music,t1.classify_id,t1.template_status,t1.option_id,t1.approvedBy,t1.deleteReason,{parent_id}" +
  238. " FROM d_flyer t1," +
  239. " (SELECT m.invite_user_id,m.adscription_org FROM m_market_invite_user m WHERE m.invite_user_id IN ({user_ids}) AND m.ma_id=?" +
  240. " {add_admin_user}) t2 " +
  241. " WHERE t1.id=? AND t1.ma_id=? AND t1.deleted=0 AND t1.user_id=?";
  242. break;
  243. case 3:// updateFlyerDetail
  244. sql = "UPDATE d_flyer_detail t1,d_flyer_detail t2" +
  245. " SET t1.content = t2.content," +
  246. " t1.updated_content = t2.updated_content," +
  247. " t1.dsc=t2.dsc" +
  248. " WHERE t1.flyer_id IN({flyer_ids}) AND t2.flyer_id = ?";
  249. break;
  250. case 4:// insertFlyerDetail
  251. sql = "INSERT INTO d_flyer_detail(flyer_id, content, updated_content, dsc) " +
  252. " SELECT t2.id, t1.content, t1.updated_content, t1.dsc " +
  253. " FROM d_flyer_detail t1,(SELECT id ,user_id FROM d_flyer WHERE id IN({flyer_ids})) t2" +
  254. " WHERE t1.flyer_id=?";
  255. break;
  256. case 5:
  257. sql =" INSERT INTO d_flyer(title,status,create_time,notice,template,user_id,update_time,description,deleted,orgid,hit,notice_days,visitor_count,feedback_count,ishot,version,is_edit,is_add,beau_sel,ma_id,isorg,refer_count,refer_id,isdraw,iscopy,is_marketa_enjoy,showTitle,searchKeyword,music,classify_id,template_status,option_id,approvedBy,deleteReason,parent_id) " +
  258. " (SELECT t1.title,t1.status,NOW(),t1.notice,t1.template,t2.user_id,NOW(),t1.description,0,t2.org_id,0,t1.notice_days,0,0,t1.ishot,2.00,t1.is_edit,t1.is_add,t1.beau_sel,t1.ma_id,0,t1.refer_count,t1.refer_id,t1.isdraw,t1.iscopy,0,t1.showTitle,t1.searchKeyword,t1.music,t1.classify_id,t1.template_status,t1.option_id,t1.approvedBy,t1.deleteReason, " +
  259. " {parent_id} " +
  260. " FROM d_flyer t1, " +
  261. " (select DISTINCT user_id, org_id from m_org_user where user_id in({user_ids}) and del=0 and dept_id !=0 ) t2 " +
  262. " WHERE t1.id=? AND t1.deleted=0 AND t1.user_id=?)";
  263. default:
  264.  
  265. }
  266.  
  267. return sql;
  268. }
  269.  
  270. /**
  271. * =====================================辅助方法清单:方法五==================================================================
  272. */
  273. private List<Map<String, Object>> getSharedFlyerInfoByUserIds(Integer maId, Integer parentId, String userIds){
  274. List<Map<String, Object>> flyers = null;
  275. String sql = "SELECT t.id AS flyer_id,t.user_id, t.orgid FROM d_flyer t WHERE t.user_id IN ({user_ids}) AND t.ma_id=? AND t.parent_id=?";
  276. sql = sql.replace("{user_ids}", userIds);
  277. Object[] params = new Object[]{maId, parentId};
  278. flyers = this.getDao().query(sql, params, null);
  279. return flyers;
  280. }
  281. /**
  282. * =====================================辅助方法清单:方法六==================================================================
  283. */
  284. private void refreshNameCard(List<Map<String, Object>> flyerDetails){
  285. if(null==flyerDetails || flyerDetails.isEmpty()){ //如果没有任何相关的表
  286. return;
  287. }
  288. for(int i=0; i<flyerDetails.size(); i++){//获取
  289. Map<String, Object> flyer = flyerDetails.get(i);
  290. Integer userId = Integer.parseInt(flyer.get("user_id").toString());//获取传单所属用户
  291. Integer flyerId = Integer.parseInt(flyer.get("flyer_id").toString());// 相关的传单id
  292. String content = flyer.get("content").toString();// 传单设置的内容
  293. //String updateContent = flyer.get("updated_content").toString();//传单发布后设置的内容 为空!!!!!!!
  294. /**辅助方法清单:方法七*/
  295. Map<String, Object> m = JsonUtil.jsonToMap(content);/**content 格式化后长度过长 会在最下面展示*/
  296. //m 是json解析的总根 ~
  297. List<Map<String,String>> widgets = (List<Map<String, String>>) m.get("widgets");
  298. for(int j=0; j<widgets.size(); j++){
  299. Map<String, String> widget = widgets.get(j);
  300. String wdUname = widget.get("wd_u_name");
  301. if("bio".equals(wdUname)){// 找到名片 复制了简单的我们需要的json数据
  302. /**辅助方法清单:方法九*/
  303. Map<String, String> newCard = replaceCardInfo(widget, userId, flyerId, flyer);//生成用户 新的名片
  304. widgets.set(j, newCard);//应该就一个 - -! 设置回去
  305. }
  306. }
  307. m.put("widgets", widgets);//用新的替换了之前的
  308. /**辅助方法清单:方法八*/
  309. String newContent = JsonUtil.objToJson(m);//重新转换成json字符串
  310. //访问数据库,开始修改detail表的数据
  311. /**辅助方法清单:方法十*/
  312. updateDetailContent(flyerId, newContent);// 更改详细信息表里面的content数据
  313.  
  314. }
  315. /**辅助方法六调用结束 返回passFlyerToUsers() 方法的调用处(倒数7行左右)*/
  316. }
  317. /**
  318. * =====================================辅助方法清单:方法九==================================================================
  319. */
  320. private Map<String, String> replaceCardInfo(Map<String, String> widget, Integer userId, Integer flyerId, Map<String, Object> userInfo){
  321. /*"wd_u_name":"bio","company":"贵州限责任公司","job":"职位","realname":"李小姐",
  322. "qq":"1234578","tell":"085-1234567","sina":"http://webo.com/baogs/ome?vr=5","email":"255123456@qq.com",
  323. "web":"http://www.e.com/","address":"贵阳号",*/
  324. Map<String, String> card = new HashMap<String, String>();
  325. Set<String> keySet = widget.keySet();// company job realname ==的key集合
  326. System.out.println("----------Start replace mobile card info[userId="+userId+",flyerId="+flyerId+"]---------------");
  327. for(String key : keySet){
  328. Object userObj = null;
  329. if("realname".equals(key)){
  330. userObj = userInfo.get("realname");
  331. } else if("qq".equals(key)){
  332. userObj = userInfo.get("qq");
  333. } else if("tell".equals(key)){
  334. userObj = userInfo.get("mobile");
  335. } else if("email".equals(key)){
  336. userObj = userInfo.get("email");
  337. } else if("phone".equals(key)){
  338. userObj = userInfo.get("phone");
  339. } else if("weixin".equals(key)){
  340. userObj = userInfo.get("weixin");
  341. } else if("job".equals(key)){
  342. userObj = userInfo.get("job")
  343. }
  344. System.out.println(key+" = "+String.valueOf(userObj));
  345. String value = "";
  346. if(null==userObj){
  347. value = String.valueOf(widget.get(key)); //没有的话 用原来的
  348. } else {
  349. value = String.valueOf(userObj); //有的话 设置进去
  350. }
  351. card.put(key, value); //放到map里面
  352. }
  353. System.out.println("----------End replace mobile card info---------------");
  354. return card; //返回回去
  355. }
  356.  
  357. /**
  358. * =====================================辅助方法清单:方法十==================================================================
  359. */
  360. private void updateDetailContent(Integer flyerId, String content){
  361. String sql = "update d_flyer_detail set content = ? where flyer_id = ?";
  362. Object[] params = new Object[]{content, flyerId};
  363. this.getDao().update(sql,params);
  364. }
  365.  
  366. /**
  367. * =====================================辅助方法清单:方法十一==================================================================
  368. */
  369. private void uploadShareFlyerHtmlFile(Integer maId, Integer flyerId, Integer userId, Integer orgId, List<Map<String, Object>> members) throws Exception{
  370. //本地html保存路径
  371. //获取ServletAction上下文对象,getServletContext()获取Servlet上下文对象(项目地址),getRealPath("file")获取file的!绝对路径! 加上/加上flyer
  372. String localHtmlRoot = ServletActionContext.getServletContext().getRealPath("file")+ File.separatorChar +"flyer";
  373. //本地共享传单路径
  374. String shareHtmlPath = localHtmlRoot + File.separator + "html" + File.separator + userId+ File.separator;
  375. //共享传单文件名称
  376. String shareFileName = flyerId + ".html"; //被共享的传单的地址拼接完成
  377.  
  378. //上传路径
  379. final String realPath = ServletActionContext.getServletContext().getRealPath("");//获取项目的绝对路径
  380. File shareFile = new File(shareHtmlPath + shareFileName); //被共享传单的File对象
  381. if(!shareFile.exists()){ // 如果不存在 则抛出异常
  382. throw new RuntimeException("共享失败,共享传单不存在!");
  383. }
  384. for(int i=0; i<members.size(); i++){ //为每一个用户复制被共享的一份传单 放到自己的/user_id/flyer_id下面
  385. String uploadFilePath = "";
  386. String tmpFileName = "";
  387. Map<String, Object> mem = members.get(i);
  388. Integer inviteUserId = (Integer) mem.get("user_id");
  389. Integer inviteUserOrg = (Integer) mem.get("orgid");
  390. Integer inviteUserFlyerId = (Integer) mem.get("flyer_id");
  391. tmpFileName = inviteUserFlyerId + ".html";
  392. String tmpFilePath = localHtmlRoot + File.separator + "html" +File.separator + inviteUserId+ File.separator;
  393. String tmpFileFullName = tmpFilePath + tmpFileName;
  394. //文件名 和文件路径判断 先有路径才能创建文件
  395. File tmpFile = new File(tmpFileFullName);
  396. File tmpDirs = new File(tmpFilePath);
  397. if(!tmpDirs.exists()){//文件路径不存在的情况下 创建文件路径
  398. tmpDirs.mkdirs();
  399. }
  400. if(tmpFile.exists()){ //如果先前文件已经存在(未删除)则进行删除
  401. tmpFile.delete();
  402. }
  403. //复制共享传单
  404. /**辅助方法清单:方法十二*/
  405. FileUtil.copyFile(shareFile, tmpFile);//建立流 复制传单
  406. if(!tmpFile.exists()){ //再次判断是否复制了传单
  407. throw new RuntimeException("共享失败,复制传单"+tmpFileName+"失败!");
  408. }
  409. // 更改了成员传单的 名片 等详细信息
  410. /**辅助方法清单:方法十三*/
  411. reloadCardHtml(tmpFile, mem);
  412. //上传成员传单html文件
  413. uploadFilePath = localHtmlRoot.replace(realPath, "") + File.separator + "html" + File.separator + inviteUserOrg + File.separator + tmpFileName;
  414. try {
  415. FileService.UpYunWriteFile(uploadFilePath, tmpFile, false);
  416. } catch (Exception e) {
  417. e.printStackTrace();
  418. }
  419. }//for循环右括号
  420. }
  421. /**
  422. * =====================================辅助方法清单:方法十三==================================================================
  423. */
  424. /** 使用了 Jsoup解析了 html文档树*/
  425. private void reloadCardHtml(File html, Map<String, Object> userInfo){
  426. // FileWriter fw = null;
  427. OutputStreamWriter writer = null;
  428. boolean flag = false;
  429. try {
  430. Integer inviteUserId = (Integer) userInfo.get("user_id");
  431. Integer inviteUserOrg = (Integer) userInfo.get("orgid");
  432. Integer inviteUserFlyerId = (Integer) userInfo.get("flyer_id");
  433. System.out.println("==========Start replace html bio[userId="+inviteUserId+",flyerId="+inviteUserFlyerId+"]========================");
  434. //http://www.jb51.net/article/43485.htm Jsoup的使用
  435. //<span class="realname" data-key="realname">“构享家”团队</span>
  436. Document doc = Jsoup.parse(html, "UTF-8");
  437.  
  438. Elements companies = doc.getElementsByAttributeValue("data-key", "company");
  439. Elements jobs = doc.getElementsByAttributeValue("data-key","job");
  440. Elements realname = doc.getElementsByAttributeValue("data-key","realname");
  441. Elements qq = doc.getElementsByAttributeValue("data-key","qq");
  442. Elements wechats = doc.getElementsByAttributeValue("data-key","weixin");
  443. Elements mobile = doc.getElementsByAttributeValue("data-key","tell");
  444. Elements phone = doc.getElementsByAttributeValue("data-key","mobile");
  445. Elements weibos = doc.getElementsByAttributeValue("data-key","sina");
  446. Elements emails = doc.getElementsByAttributeValue("data-key","email");
  447. Elements webs = doc.getElementsByAttributeValue("data-key","web");
  448. Elements address = doc.getElementsByAttributeValue("data-key","address");
  449.  
  450. String userCompany = String.valueOf(userInfo.get("company")==null?"":userInfo.get("company"));
  451. String userJob = String.valueOf(userInfo.get("job") == null ? "" : userInfo.get("job"));
  452. String userQQ = String.valueOf(userInfo.get("qq")==null?"":userInfo.get("qq"));
  453. String userMobile = String.valueOf(userInfo.get("mobile")==null?"":userInfo.get("mobile"));
  454. String userPhone = String.valueOf(userInfo.get("phone")==null?"":userInfo.get("phone"));
  455. String userRealname = String.valueOf(userInfo.get("realname")==null?"":userInfo.get("realname"));
  456. String userEmail = String.valueOf(userInfo.get("email")==null?"":userInfo.get("email"));
  457. String userWeixin = String.valueOf(userInfo.get("weixin")==null?"":userInfo.get("weixin"));
  458. if(null!=realname && realname.size()>0){
  459. Element e = realname.get(0);
  460. e.text(userRealname);//给元素内容设置数据
  461. System.out.println("realname="+userRealname);
  462. flag = true;
  463. }
  464.  
  465. if(null!=phone && phone.size()>0){
  466. Element e = phone.get(0);
  467. e.text(userPhone);
  468. System.out.println("phone="+userPhone);
  469. flag = true;
  470. }
  471.  
  472. if(null!=mobile && mobile.size()>0){
  473. Element e = mobile.get(0);
  474. e.text(userMobile);
  475. System.out.println("mobile="+userMobile);
  476. flag = true;
  477. }
  478.  
  479. if(null!=qq && qq.size()>0){
  480. Element e = qq.get(0);
  481. e.text(userQQ);
  482. System.out.println("qq="+userQQ);
  483. flag = true;
  484. }
  485.  
  486. if(null!=emails && emails.size()>0){
  487. Element e = emails.get(0);
  488. e.text(userEmail);
  489. System.out.println("email="+userEmail);
  490. flag = true;
  491. }
  492.  
  493. if(null!=wechats && wechats.size()>0){
  494. Element e = wechats.get(0);
  495. e.text(userWeixin);
  496. System.out.println("weixin="+userWeixin);
  497. flag = true;
  498. }
  499. System.out.println("==========End replace html bio[userId="+inviteUserId+",flyerId="+inviteUserFlyerId+"]========================");
  500. if(flag){ //如果有更改 in √
  501. String htmlContent = doc.html();//doc对象的内容已经变了? 现在实际上是jsoup一次性解析了html文件
  502. // 生成 Document对象 一直在内存中 我们只是操作了对象
  503. // String aaa = doc.data(); 测试代码
  504. // String bbb = doc.html();
  505. // String ccc = doc.val();
  506. // fw = new FileWriter(html);
  507. // fw.write(htmlContent);
  508. writer = new OutputStreamWriter(new FileOutputStream(html), "UTF-8"); //开启了到更新文件的 输出流
  509. writer.write(htmlContent); //把文档输出到里面去 内存到硬盘的写入
  510. writer.close();
  511. }
  512. } catch (Exception e) {
  513. e.printStackTrace();
  514. }
  515. }
  516. }

两个工具类(不完全):

  1. //--------------------------JsonUtil类---------使用了google提供的 gson类 解析json-a------------------------------------------------------
  2. import com.google.gson.Gson;
  3. import com.google.gson.GsonBuilder;
  4. import com.google.gson.reflect.TypeToken;
  5.  
  6. public class JsonUtil{
  7. private static Gson gson;
  8. /** JSON字符串转化为HashMap对象*/
  9. /**
  10. * =====================================辅助方法清单:方法七==================================================================
  11. */
  12. public static Map<String, Object> jsonToMap(String string) {
  13. Map<String, Object> obj = null;
  14. try { //s使用 google的gson包
  15. obj = JsonUtil.getGson().fromJson(string, new TypeToken<Map<String, Object>>(){}.getType());
  16. }catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. return obj;
  20. }
  21. /**
  22. * =====================================辅助方法清单:方法八==================================================================
  23. */
  24. public static String objToJson(Object data) {
  25. try {
  26. return JsonUtil.getGson().toJson(data);
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. return "";
  31. }
  32. }
  33.  
  34. //--------------------------FileUtil类---------使用了google提供的 gson类 解析json-a------------------------------------------------------
  35. public class FileUtil {
  36. /**
  37. * =====================================辅助方法清单:方法十二==================================================================
  38. */
  39. public static boolean copyFile(File sourceFile, File targetFile) {
  40. try {
  41. BufferedInputStream inBuff = null;
  42. BufferedOutputStream outBuff = null;
  43. try {
  44. // 新建文件输入流并对它进行缓冲
  45. inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
  46.  
  47. // 新建文件输出流并对它进行缓冲
  48. outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
  49. // 缓冲数组
  50. byte[] b = new byte[1024 * 100];
  51. int len;
  52. while ((len = inBuff.read(b)) != -1) {
  53. outBuff.write(b, 0, len);
  54. }
  55. // 刷新此缓冲的输出流
  56. outBuff.flush();
  57. } finally {
  58. // 关闭流
  59. if (inBuff != null)
  60. inBuff.close();
  61. if (outBuff != null)
  62. outBuff.close();
  63. }
  64. } catch (Throwable e) {
  65. e.printStackTrace();
  66. return false;
  67. }
  68. return true;
  69. }
  70.  
  71. }

/**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ content内容展~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  1. /*
  2. {"widgets":
  3. [
  4. {"wd_u_name":"title",
  5. "value":"找工作去劳联,电信送手机",
  6. "href":"http://baidu.com",
  7. "color":"#000000",
  8. "colors":[
  9. "#000000",
  10. "#ff7418",
  11. "#f14444",
  12. "#a25c18",
  13. "#b62450"],
  14. "fontSize":"25px",
  15. "fontFamily":"Microsoft YaHei,Microsoft YaHei",
  16. "marginTop":"10px",
  17. "textAlign":"center"},
  18.  
  19. {"wd_u_name":"map",
  20. "value":"北京市海淀区上地信息路28号科实大厦",
  21. "marginTop":"5px"},
  22. {"wd_u_name":"media",
  23. "value":"http://player.youku.com/player.php/sid/XNjY0NDI4MjE2/v.swf",
  24. "color":"#000000",
  25. "marginTop":"5px"},
  26.  
  27. {"wd_u_name":"feedback", //反馈表
  28. "btnLabel":"抢购",
  29. "items":
  30. [
  31. {"name":"name",
  32. "allowBlank":"false",
  33. "label":"姓 名 "},
  34. {"name":"weibo",
  35. "label":"微博",
  36. "maxlength":64,
  37. "input":"string",
  38. "width":"100",
  39. "allowBlank":"true"},
  40. {"name":"phone",
  41. "label":"电话",
  42. "maxlength":32,
  43. "sortable":true,
  44. "type":"string",
  45. "width":"100",
  46. "allowBlank":"false"},
  47. {"name":"mobile",
  48. "label":"手     机",
  49. "allowBlank":"false"},
  50. {"name":"appellation",
  51. "label":"称呼",
  52. "maxlength":32,
  53. "input":"string",
  54. "width":"100",
  55. "allowBlank":"true"},
  56. {"name":"email",
  57. "label":"邮 箱 ",
  58. "allowBlank":"true"},
  59. {"name":"position",
  60. "label":"经纪人",
  61. "maxlength":32,
  62. "input":"string",
  63. "width":"100",
  64. "allowBlank":"false"},
  65. {"name":"note",
  66. "label":"备注",
  67. "maxlength":200,
  68. "type":"string",
  69. "input":"textarea",
  70. "width":"150"},
  71. {"name":"company",
  72. "label":"公司",
  73. "maxlength":64,
  74. "sortable":true,
  75. "input":"string",
  76. "width":"150"},
  77. {"name":"qq",
  78. "label":"QQ",
  79. "allowBlank":"true"},
  80. {"name":"address",
  81. "label":"地址",
  82. "maxlength":128,
  83. "type":"string",
  84. "width":"100",
  85. "allowBlank":"true"}
  86. ],
  87. "fontSize":"13px",
  88. "marginTop":"10px"},
  89.  
  90. -------------//名片表-----------------------主要是他更新 因为传单的名片应该是发到A的账号中去的时候就变成A的相关的信息 当然也可以编辑
  91. {"wd_u_name":"bio",
  92. "company":"贵州限责任公司",
  93. "job":"职位",
  94. "realname":"李小姐",
  95. "qq":"",
  96. "tell":"08516550",
  97. "sina":"http://webo.com/baogs/ome?vr=5",
  98. "email":"2556890@qq.com",
  99. "web":"http://www.e.com/",
  100. "address":"贵阳号",
  101. "marginTop":"0px",
  102. "imgsrc":"/file/flyer/tdcode/png201431118063553.png",
  103. "status":2,
  104. "fontSize":"18px",
  105. "color":"rgb(0,
  106. 0,
  107. 0)",
  108. "colors":["#000000",
  109. "#7f8c2f",
  110. "#85622a",
  111. "#b66c2a",
  112. "#a92e2e"]}
  113. ],
  114. "meta":{"color":"#fedac2",
  115. "bgImg":"/flyer/images/flyerimg/flyer_bg_6.jpg",
  116. "shadingImg":"/flyer/images/bgimg/06.png"}}
  117. */

OK  结束   再次声明 此博客为个人笔记      并不是独立demo

项目开发笔记-传单下发 名片替换 文件复制上传/html静态内容替换/json解析/html解析的更多相关文章

  1. Gin-Go学习笔记四:Gin-Web框架 文件的上传下载

    文件的上传和下载 1->文件的上传 文件的上传,采用的是uploadify.js这个插件. 本事例实现的是上传图片文件,其他的文件上传也一样. 2->文件的下载 文件的下载有两个实现的方式 ...

  2. Android应用开发之使用Socket进行大文件断点上传续传

    http://www.linuxidc.com/Linux/2012-03/55567.htm http://blog.csdn.net/shimiso/article/details/8529633 ...

  3. SpringMVC听课笔记(十二:文件的上传)

    1.Spring MVC为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的.Spring用Jakarta Commons FileUpload技术实现了一个M ...

  4. Spring MVC 实现文件的上传和下载

    前些天一位江苏经贸的学弟跟我留言问了我这样一个问题:“用什么技术来实现一般网页上文件的上传和下载?是框架还是Java中的IO流”.我回复他说:“使用Spring MVC框架可以做到这一点,因为Spri ...

  5. linux链接及文件互相上传下载

    若排版紊乱可查看我的个人博客原文地址 基本操作 本篇博客主要介绍如何去链接远程的linux主机及如何实现本地与远程主机之间文件的上传下载操作,下面的linux系统是CentOS6.6 链接远程linu ...

  6. java web(四):request、response一些用法和文件的上传和下载

    上一篇讲了ServletContent.ServletCOnfig.HTTPSession.request.response几个对象的生命周期.作用范围和一些用法.今天通过一个小项目运用这些知识.简单 ...

  7. [Openwrt 项目开发笔记]:Openwrt平台搭建(一)

    [Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 最近开始着手进行Openwrt平台的物联网网关设 ...

  8. [Openwrt 项目开发笔记]:PHP+Nginx安装(七)

    [Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我们已经搭建了MySQL数据库了,因 ...

  9. [Openwrt 项目开发笔记]:MySQL配置(六)

    [Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在本人的项目中,运行在路由器上的服务器采用Ngi ...

随机推荐

  1. leetcode—Best Time to Buy and Sell stocks III

    1.题目描述 Say you have an array for which the ith element is the price of a given stock on day i.   Des ...

  2. 【转载】C/C++语言void及void指针深层探索

    C/C++语言void及void指针深层探索 1.概述许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述vo ...

  3. connect to a specific wifi network in Android programmatically

    http://stackoverflow.com/questions/8818290/how-to-connect-to-a-specific-wifi-network-in-android-prog ...

  4. POJ 2749--Building roads(2-SAT)

    题意:John有n个牛棚,每个牛棚都住着一些牛,这些牛喜欢串门(drop around, 学到了...),所以John想要建几条路把他们连接起来.他选择的方法是建两个相连中转站,然后每个牛棚连接其中一 ...

  5. keil中的存储模式

    存储模式 存储模式决定了默认的存储器类型此存储器类型将应用于函数参数局部变量和定义时未包含存储器类型的变量你可以在命令行用SMALL COMPACT和LARGE参数定义存储模式,定义变量时使用存储器类 ...

  6. Codeforces Wilbur and Array

    Description Wilbur the pig is tinkering with arrays again. He has the array a1, a2, ..., an initiall ...

  7. hdoj 2120 Ice_cream's world I【求成环数】

    Ice_cream's world I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. C#基础知识回顾-- 反射(1)

    C#基础知识回顾-- 反射(1)   反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...

  9. java--静态的应用(工具类)

    ArrayTool.java文件 /** 静态的应用. 每一个应用程序中都有公行动的功能,可以将这些功能进行抽取,独立封装以便复用 由于ArrayTool中并没有封装特有数据,而且数组的每一个方法也没 ...

  10. hdu 2844 Coins (多重背包)

    题意是给你几个数,再给你这几个数的可以用的个数,然后随机找几个数来累加, 让我算可以累加得到的数的种数! 解题思路:先将背包初始化为-1,再用多重背包计算,最后检索,若bb[i]==i,则说明i这个数 ...