月份:2018年7月

Layui 下拉框省市联动-后台查询方式

33334.gif

实现的效果就是上面这样,省市联动,由于对前端掌握的并不是很好,就用后台交互的方式实现了一下。

实现原理:在页面加载时初始化省份下拉框,然后监听下拉框点击事件,点击后,市下拉框加载数据。

数据库中cid为每个省份中市的顺序,根据省份选择的省份名获取pid与city表中的pid比较,然后获取城市名字。

1.数据库sql

—省:province.sql

    http://p8rwym8v0.bkt.clouddn.com/province.sql

—市:city.sql

    http://p8rwym8v0.bkt.clouddn.com/city.sql

image.pngimage.png

可以看出,市是由省份pid关联的。

2.实体类-entity

—ProvinceEntity.java

import java.io.Serializable;

/**
 * @author 
 */
public class ProvinceEntity implements Serializable {
    /**
     * 省份id
     */
    private Long pid;

    /**
     * 省份
     */
    private String province;

    private static final long serialVersionUID = 1L;

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }
}

—CityEntity.java

import java.io.Serializable;

/**
 * @author 
 */
public class CityEntity implements Serializable {
    /**
     * 市序号
     */
    private Long cid;

    /**
     * 市
     */
    private String city;

    /**
     * 所属省id
     */
    private Long pid;

    private static final long serialVersionUID = 1L;

    public Long getCid() {
        return cid;
    }

    public void setCid(Long cid) {
        this.cid = cid;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }
}

3.mapper.xml

—ProvinceMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xxx.dao.ProvinceDao">
  <resultMap id="BaseResultMap" type="xxx.entity.ProvinceEntity">
    <id column="pid" jdbcType="BIGINT" property="pid" />
    <result column="province" jdbcType="VARCHAR" property="province" />
  </resultMap>

  <sql id="Base_Column_List">
    pid, province
  </sql>
  
  <select id="getAllProv" resultMap="BaseResultMap">
    select
      <include refid="Base_Column_List" />
    from
    datav_province
    order by pid asc
  </select>

  <select id="getPidByProvince" resultType="java.lang.Long">
    select
      pid
    from
      datav_province
    where
      province = #{province,jdbcType=VARCHAR}
  </select>
</mapper>

—CityMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xxx.dao.CityDao">
  <resultMap id="BaseResultMap" type="xxx.entity.CityEntity">
    <result column="cid" jdbcType="BIGINT" property="cid" />
    <result column="city" jdbcType="VARCHAR" property="city" />
    <result column="pid" jdbcType="BIGINT" property="pid" />
  </resultMap>

  <sql id="Base_Column_List">
    cid, city, pid
  </sql>

  <select id="getCityByPid" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select
      <include refid="Base_Column_List"/>
    from
    datav_city
    where pid = #{pid,jdbcType=BIGINT}
    order by cid asc
  </select>

</mapper>

4.dao.java

—ProvinceDao.java

import java.util.List;
 /**
 * 省份dao
 * @author wujianyu
 * @date 2018/7/31
 */
public interface ProvinceDao {
    /**
    * 查询所有省份
    * @return list
    * @author wujianyu
    * @date 2018/7/31
    */
    List<ProvinceEntity>  getAllProv();

    /**
    * 根据省获取省id
    * @param  province
    * @return  pid
    * @author wujianyu
    * @date 2018/7/31
    */
    Long getPidByProvince(String province);
}

—CityDao.java

import java.util.List;
/**
* 城市dao
* @author wujianyu
* @date 2018/7/31
*/
public interface CityDao {
    /**
    * 根据省份id获取城市列表
    * @param  pid 省份id
    * @return  list
    * @author wujianyu
    * @date 2018/7/31
    */
    List<CityEntity> getCityByPid(Long pid);
}

5.service.java 和serviceImpl.java

—ProvinceCityService.java

import com.alibaba.fastjson.JSONArray;

/**
 * @author wjy329
 * @date 2018/7/31
 * @description ${description}
 */
public interface ProvCityService {
    /**
    * 获取所有的省份
    * @return
    * @author wujianyu
    * @date 2018/7/31
    */
    JSONArray queryAllProv();

    /**
     * 根据省份id获取城市
     * @param pid
     * @return
     * @author wujianyu
     * @date 2018/7/31
     */
    JSONArray queryCityByPid(Long pid);

    /**
    * 根据省份获取省份id
    * @param  province
    * @return
    * @author wujianyu
    * @date 2018/7/31
    */
    Long queryPidByProvince(String province);
}

—ProvinceCityServiceImpl.java

import java.util.List;

/**
 * @author wjy329
 * @date 2018/7/31
 * @description ${description}
 */
@Service
public class ProvCityServiceImpl implements ProvCityService {
    @Autowired
    ProvinceDao provinceDao;
    @Autowired
    CityDao cityDao;
    @Override
    public JSONArray queryAllProv() {
        List<ProvinceEntity> result = provinceDao.getAllProv();
        return (JSONArray) JSONArray.parse(JSON.toJSON(result).toString());
    }

    @Override
    public JSONArray queryCityByPid(Long pid) {
        List<CityEntity> result = cityDao.getCityByPid(pid);
        return (JSONArray) JSONArray.parse(JSON.toJSON(result).toString());
    }

    @Override
    public Long queryPidByProvince(String province) {
        Long pid = provinceDao.getPidByProvince(province);
        return pid;
    }
}

6.ProvinceCityController.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author wjy329
 * @date 2018/7/31
 * @description ${description}
 */
@Controller
@RequestMapping("/district")
public class ProvCityController {
    @Autowired
    ProvCityService provCityService;

    @ResponseBody
    @RequestMapping(value = "/prov", produces = "application/json;charset=UTF-8")
    public JSONArray provList() {
        //从数据库中获取到数据
        JSONArray rs = this.provCityService.queryAllProv();
        return rs;
    }

    @ResponseBody
    @RequestMapping(value = "/city", produces = "application/json;charset=UTF-8")
    public JSONArray cityList(String province) {
        Long pid = this.provCityService.queryPidByProvince(province);
        //从数据库获取数据
        JSONArray rs = this.provCityService.queryCityByPid(pid);
        return rs;
    }
}

7.index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>update页面展示</title>
    <link rel="stylesheet" href="/plugins/layui/css/layui.css" media="all" />
    <link rel="stylesheet" href="/css/index/common.css" media="all" />

    <!-- 配置脚本 -->
    <script th:src="@{/plugins/layui/layui.js}"></script>
    <script th:src="@{/plugins/jquery/jquery.min.js}"></script>
    <script th:src="@{/js/index.js}"></script>
</head>
<body class="childrenBody">
<div class="layui-inline">
<form class="layui-form" id="form" style="margin: 10px" action="">
    <div class="layui-form-item">
        <label class="layui-form-label">选择地区</label>
        <div class="layui-input-inline">
            <select name="prov" id="prov" lay-filter="prov">
                <option value="">请选择省</option>
            </select>
        </div>
        <div class="layui-input-inline">
            <select name="city" id="city" lay-filter="city">
                <option value="">请选择市</option>
            </select>
        </div>
    </div>
    <div class="layui-form-item">
    <div class="layui-input-inline" >
        <button class="layui-btn"  lay-submit="" lay-filter="update_btn" id="update_btn">查询</button>
    </div>
    </div>
</form>
</div>
</body>
</html>

8.index.js

layui.use(['form', 'laydate','jquery'], function () {
    var form = layui.form,
         layer = layui.layer,
        laydate = layui.laydate,
        $ = layui.$;

    getProv();
   
    function getProv() {
        $('#prov').html(""); //每次点击清除数据
        $.ajax({
            url: "/district/prov",
            type: "get",
            dataType: "json",
            success: function (result) {
                var optionString = "";
                $.each(result, function (index, item) {
                    optionString +="<option value=" + item.province
                        + ">" + item.province + "</option>"
                });
                $('#prov').append("<option value=''>请选择省</option> "
                    +optionString);
                form.render('select');
            }
        });
    }
    form.on('select(prov)', function(data){
        //得到被选中的省
        var prov = data.value;
        //根据省获取市
        getCity(prov);
    });
    function getCity(prov) {
        $('#city').html(""); //每次点击清除数据
        $.ajax({
            url: "/district/city?province="+prov,
            type: "get",
            dataType: "json",
            success: function (result) {
                var optionString = "";
                $.each(result, function (index, item) {
                    optionString +="<option value=" + item.city
                        + ">" + item.city + "</option>"
                });
                $('#city').append("<option value=''>请选择市</option> "
                    +optionString);
                form.render('select');
            }
        });
    }
});

页面实现点击添加到文本框效果

也不知道这个到底是什么,就简单记录一下,就是实现点击下拉框添加到一个框中,可以判断重复,也可以点击删除,在网上找了些没找到合适的,自己简单的弄了一个。很丑,别介意。。。

0.实现的原理

    下拉选择框下面是一个隐藏的input,input的value是提交的数据,随着点击事件动态改变,负责显示的是一个div,div中动态的添加<li>,即可实现所需的效果;

1.html

我这里是基于layui,所以引入layui的js和css,还需引入自己写的labeltags.csslabeltags.js;

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
   <link rel="stylesheet" href="/plugins/layui/css/layui.css" media="all" />
   <!-- 标签文本的样式 -->
   <link rel="stylesheet" href="/plugins/tags/css/labeltags.css"/>
</head>
<body class="childrenBody">
    <div id="userAdd">
       <form class="layui-form"  action="" id="Form" >
          <div class="dialogForm" style="margin-top:20px;padding-right: 80px;">
         
            <div class="layui-form-item">
               <label class="layui-form-label">选择人</label>
               <div class="layui-input-block">
                  <select id="allUser" name="allUser" lay-filter="allUser" lay-verify="" lay-search>
                  </select>
               </div>
            </div>
            <div class="layui-form-item" style="display: none">
               <div class="layui-input-block">
                  <input type="text" class="layui-input" id="user" name="user">
               </div>
            </div>

            <div class="layui-form-item">
               <div class="layui-input-block">
                  <div class="label-box" id="labelBox"></div>
               </div>
            </div>

           
            <div class="layui-form-item">
               <div class="layui-input-block">
                  <button class="layui-btn" lay-submit="" lay-filter="addGetForm" >立即提交</button>
                  <button type="reset" id="btnReset" class="layui-btn layui-btn-primary">重置</button>
                </div>
            </div>
          </div>
       </form>
    </div>
   <script type="text/javascript" src="/plugins/layui/layui.js"></script>
   <script type="text/javascript" src="/js/labeltags.js"></script>
</body>
</html>

2.labeltags.css

li{display:inline-block; width:100px; height:20px; border:1px solid #E6E6E6;margin:2px; text-align: center; -moz-border-radius: 15px;
    -webkit-border-radius: 15px;
    border-radius:15px;}
.label-box{width:300px;height:100px;border:1px solid #E6E6E6;border-top:2px solid #E6E6E6;border-radius:3px; overflow-x: hidden;overflow-y: scroll;}
.label-box span{display:inline-block;background:#99CCFF;padding:6px 14px;color:#fff;border-radius:3px;margin:0 3px;}

3.labeltags.js (只写出实现效果核心的js)

layui.config({
     base: '/js/modules/' 
}).use(['form','layer','table','jquery','laypage'],function(){
   var form = layui.form,
      layer = parent.layer === undefined ? layui.layer : parent.layer,
      laypage = layui.laypage,
      table = layui.table,
      $ = layui.jquery;
    //初始化下拉框,获取所有用户的名字
    getUsers();

    form.on('select(allUser)', function(data){
        console.log(data.value); //得到被选中的值
        var userInput = $("#user").val();//先拿到input的值
        //判断input的值,如果为空直接添加,不为空的话将逗号和值添加
        if(userInput != "" && userInput != undefined){
            var valObj = userInput.split(",");
            for ( var i = 0; i <valObj.length; i++){
                if(valObj[i] == data.value){
                    layer.msg('名字已存在', {time: 1000, icon:2});
                    return false;
                }
            }
        }
        //上面判断完成后添加到div中的li
      $('#labelBox').append("<li>"+"<i class='layui-icon'>&#x1006;</i>"+"<a>"+data.value+"</a>"+"</li>");
        if($("#user").val()==""||$("#user").val()==null){
            $("#user").val(data.value);
        }else{
            $("#user").val($("#user").val()+","+data.value);
        }
    });
    //li的点击事件,点击后删除
    $('#labelBox').on('click','li',function () {
       var closeText = $(this).find('a').text();
        console.log(closeText);
        $(this).remove();
        var userInput = $("#user").val();//先拿到input的值
        //删除点击的li对应的input的value
        if(userInput != "" && userInput != undefined){
            var valObj = userInput.split(",");
            $("#user").val('');
            for ( var i = 0; i <valObj.length; i++){
                if(valObj[i] != closeText){
                    if($("#user").val()==""||$("#user").val()==null){
                        $("#user").val(valObj[i]);
                    }else{
                        $("#user").val($("#user").val()+","+valObj[i]);
                    }
                }
            }
        }
    });

   
   //获取用户
   function getUsers() {
        $('#allUser').html(""); //每次点击清除数据
        $.ajax({
            url: "/user/getList",
            type: "get",
            dataType: "json",
            success: function (result) {
                $.each(result, function (index, item) {
                    $('#allUser').append("<option value=" + item.username
                        + ">" + item.username + "</option>")
                });
                form.render('select');
            }
        });
    }

});

4.效果展示:

3333.gif

这个展示的动态的li的添加和删除。

33334.gif

Java之爬虫学习(二) 多线程爬虫

这篇记录一下多线程爬虫的知识,准备爬取一本网络小说《最强狂兵》,在网上随便找的,哈哈,先看目录结构。

image.png

0.准备工作-分析网站结构

检查元素,我们可以看到需要的信息都在<tbody></tbody>标签中,所以我们获取tbody中的含有href的a元素即可获取第一层

image.png

再看每章小说的具体内容页,可以看到每章的内容都在id=“content”中,所以可以根据id获取元素中的文本即为每章内容。

image.png

有了上面网站结构的分析,爬取工作就很简单了,下面开始爬取小说。

1.常量-Constant.java

package com.wjy329.hello.common;

/**
 * @author wjy329
 * @date 2018/7/27
 * @description ${description}
 */
public class Constant {
    //爬取链接的网站
    public static final String URL = "https://www.23us.so/files/article/html/4/4236/index.html";
    //保存文件的目录
    public static final String PATH = "/Users/wjy329/desktop/zuiqiang";
}

2.图书实体-BookEntity.java

package com.wjy329.hello.entity;/**
 * @Author: wjy329
 * @Time: 2018/7/28下午3:21
 */

/**

 * @description: 书实体类
 *
 * @author: wjy329
 * @param:
 * @return:
 * @create: 2018-07-28 15:21
 **/
public class BookEntity {
    //章标题
    private String title;
    //内容
    private String content;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

3.String转文件工具类-FileUtil.java

package com.wjy329.hello.util;/**
 * @Author: wjy329
 * @Time: 2018/7/28下午3:28
 */

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**

 * @description: 将文字转为txt
 *
 * @author: wjy329
 * @create: 2018-07-28 15:28
 **/
public class FileUtils {

    public static void copyStr2File(String str, File outFile) {
        FileWriter out = null;
        try {
        //判断目录是否存在
            if(!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            //将字符串转化为文件
            out = new FileWriter(outFile);
            char[] chars = str.toCharArray();
            out.write(chars, 0, chars.length);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

4.主类-DataService.java

package com.wjy329.hello.service;


import com.wjy329.hello.common.Constant;
import com.wjy329.hello.thread.BookThread;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;


import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author wjy329
 * @date 2018/7/27
 * @description ${description}
 */
public class DataService {

    public static void main(String[] args) throws IOException {
        String removeStr="正文 ";
        //存放小说信息,章名,链接
        Map<String,String> bookInfo = new ConcurrentHashMap<>();
        Document document = Jsoup.connect(Constant.URL)
                //模拟火狐浏览器
                .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")
                .get();
        Elements post = document.select("tbody");
        Elements links = post.select("a[href]");
        //遍历获取的所有链接信息
        for (Element element : links) {
            //获取章节名
            String title = element.text();
            //有的章节名字钱包含正文二字,去掉这两个字
            String bookTitle = title.replace(removeStr,"");
            //获取每章对应的url
            String bookUrl = element.attr("href");
            bookInfo.put(bookTitle,bookUrl);
        }
        //开启线程
        BookThread t =new BookThread(bookInfo);

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

5.图书线程-BookThread.java

package com.wjy329.hello.thread;/**
 * @Author: wjy329
 * @Time: 2018/7/28下午3:13
 */

import com.wjy329.hello.common.Constant;
import com.wjy329.hello.entity.BookEntity;
import com.wjy329.hello.util.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

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

/**

 * @description: 线程
 *
 * @author: wjy329
 * @param:
 * @return:
 * @create: 2018-07-28 15:13
 **/
public class BookThread implements Runnable{
    private Map<String,String> bookInfo;
    public BookThread(Map<String,String> bookInfo){
        super();
        this.bookInfo = bookInfo;
    }
    @Override
    public void run() {
        //书信息不为空,循环执行
        while (bookInfo.size() > 0){
                try {
                    for (Map.Entry<String,String> entry : bookInfo.entrySet()) {
                        //加锁,使每个线程各自有自己的锁
                        synchronized (this) {
                            BookEntity bookEntity = getContent(entry.getKey(), entry.getValue());
                            FileUtils.copyStr2File(bookEntity.getContent(), new File(Constant.PATH + File.separator + bookEntity.getTitle() + ".txt"));
                            System.out.printf("当前线程%s,文章名称%s\n", Thread.currentThread().getName(), bookEntity.getTitle());
                            bookInfo.remove(entry.getKey());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
    /**
    
     * @description: 获取每章对应的具体内容
     *
     * @author: wjy329
     * @param:
     * @return:
     * @create: 2018-07-28 15:13
     **/
    private BookEntity getContent(String bookTitle,String bookUrl) throws IOException {
        BookEntity entity = new BookEntity();
        Document document = Jsoup.connect(bookUrl)
                //模拟火狐浏览器
                .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")
                .get();
        Element main = document.getElementById("contents");
        String content = main.text();
        entity.setTitle(bookTitle);
        entity.setContent(content);
        return entity;
    }

}

运行结果:

可以看到4个线程都在获取不同的内容

image.png

保存到电脑的txt

image.png

参考博客:https://blog.csdn.net/yelllowcong/article/details/78622320

Java之爬虫学习(一)

主要工具:Jsoup

1.分析网页结构

先看分页信息,前缀一样,后缀每隔50条数据是一页,总共有75100条数据,这样我们就可以用循环来换取所有的url

 image.png

代码:

/**
     * @Description: 获取请求的所有url
     * @Param: []
     * @return: java.util.List<java.lang.String>
     * @Author: wjy329
     * @Date: 2018/7/28
     */
    private static List<String> urls() {
        List<String> urls = new ArrayList<>();
        String mainUrl = "http://tieba.baidu.com/f?kw=%E5%BA%94%E5%8E%BF&ie=utf-8&pn=";
        for (int i = 0; i <= 75100; i = i + 50) {
            String url = mainUrl + i;
            urls.add(url);
        }
        return urls;
}

再看帖子主要结构

 image.png

所有的帖子信息都在<ul id=”thread_list”></ul>中,我们所需的标题和链接在<div class=”threadlist_title”><a href=”xxx” title=”标题”>标题</a></div>

title中的文字和文本一样,我们取其中一个就可以了。

//用Jsoup请求和获取信息
Document document = Jsoup.connect(url)        
//模拟火狐浏览器        
       .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)") 
       .get();
//根据thread_list获取主要信息
Element main = document.getElementById("thread_list");
//根据div.class即div.threadlist_title获取含有信息的块
Elements post = main.select("div.threadlist_title");
//根据a[href]获取包含href的a元素
Elements links = post.select("a[href]");
for (Element element : links) {    
PostEntity entity = new PostEntity();
//直接获取文本    
String title = filterEmoji(element.text());
// Node.attr(String key) 方法来取得a元素的href属性    
String linkHref = filterEmoji(url_p+element.attr("href"));    
System.out.println("已经入库信息---" + "title:" + title + "===" + "link:" + linkHref);    entity.setTitle(title);    entity.setContent(linkHref);    //插入数据库    postService.addPost(entity);}

主要代码就是这样了,我们来看效果。控制台输出和数据库保存。如果继续想深入,可以按相同的方法请求获取到的帖子链接,分析网页结构后去所需信息。

 2.运行效果

image.pngimage.png

3.全部代码

package com.wjy329.hello.controller;/**
 * @Author: wjy329
 * @Time: 2018/7/28下午12:32
 */

import com.wjy329.hello.entity.PostEntity;
import com.wjy329.hello.service.PostService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**

 * @description: controller
 *
 * @author: wjy329
 * @create: 2018-07-28 12:32
 **/
@Controller
@RequestMapping("/post")
public class postController {
    @Autowired
    PostService postService;

    @RequestMapping("/start")
    public String start() throws IOException {
        List<String> urls = urls();
        reqData(urls);
        return "index";
    }

    /**
     * @Description: 获取请求的所有url
     * @Param: []
     * @return: java.util.List<java.lang.String>
     * @Author: wjy329
     * @Date: 2018/7/28
     */
    private static List<String> urls() {
        List<String> urls = new ArrayList<>();
        String mainUrl = "http://tieba.baidu.com/f?kw=%E5%BA%94%E5%8E%BF&ie=utf-8&pn=";
        for (int i = 0; i <= 75100; i = i + 50) {
            String url = mainUrl + i;
            urls.add(url);
        }
        return urls;
    }

    /**
     * @Description: 请求数据
     * @Param: [urls]
     * @return: void
     * @Author: wjy329
     * @Date: 2018/7/28
     */
    private void reqData(List<String> urls) throws IOException {
        //帖子链接前缀
        String url_p = "http://tieba.baidu.com/";
        for (String url : urls) {
            //获取信息
            Document document = Jsoup.connect(url)
                    //模拟火狐浏览器
                    .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")
                    .get();
            Element main = document.getElementById("thread_list");
            Elements post = main.select("div.threadlist_title");
            Elements links = post.select("a[href]");
            for (Element element : links) {
                PostEntity entity = new PostEntity();
                String title = filterEmoji(element.text());
                String linkHref = filterEmoji(url_p+element.attr("href"));
                System.out.println("已经入库信息---" + "title:" + title + "===" + "link:" + linkHref);
                entity.setTitle(title);
                entity.setContent(linkHref);
                //插入数据库
                postService.addPost(entity);
            }
            //5秒后请求一次
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 判别是否包含Emoji表情
    private static boolean containsEmoji(String str) {
        int len = str.length();
        for (int i = 0; i < len; i++) {
            if (isEmojiCharacter(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    private static boolean isEmojiCharacter(char codePoint) {
        return !((codePoint == 0x0) ||
                (codePoint == 0x9) ||
                (codePoint == 0xA) ||
                (codePoint == 0xD) ||
                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)));

    }

    public static String filterEmoji(String source) {
        if (!containsEmoji(source)) {
            return source;// 如果不包含,直接返回
        }

        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (!isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            } else {
            }
        }
        if (buf == null) {
            return "";
        } else {
            if (buf.length() == len) {// 这里的意义在于尽可能少的toString,因为会重新生成字符串
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
    }

}

今天就搞一个简单的单线程爬虫。。。之后再学习。

CentOS之Java安装

官方路径:http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk8-downloads-2133151-zhs.html

1、下载

从官方下载所需的jdk版本

image.png

2、解压

我这里放到/usr/local 中,然后解压

cd /usr/local
tar -zxvf jdk-8u171-linux-x64.tar.gz

3、配置

使用 vim /etc/profile 将下面的配置复制即可,记得更换jdk路径。

export JAVA_HOME=/usr/local/jdk1.8.0_171
export JRE_HOME=/usr/local/jdk1.8.0_171/jre
export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

4、配置生效

使用如下命令使配置生效

source /etc/profile

 5、查看结果

输入:

java -version

看到版本号输出即安装成功。image.png

IDEA Sprinboot项目WAR包生成

准备工作:

启动类继承SpringBootServletInitializer 

@SpringBootApplication
@EnableAutoConfiguration
//打包需要继承SpringBootServletInitializer
public class HelloApplication extends SpringBootServletInitializer {
    //打包必须实现方法
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(HelloApplication.class);
    }
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

pom.xml中需要添加:

<packaging>war</packaging>

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
            <warSourceExcludes>src/main/resources/**</warSourceExcludes>
            <warName>test</warName>
        </configuration>
    </plugin>
</plugins>

1、终端命令打包

打开终端,输入 

mvn clean package -Dmaven.test.skip=true

等待成功即可,然后在target中可以看到生成的war包

image.png

2、Maven项目打包

其实道理是一样的,只是操作上的差异,打开idea右边的maven项目,然后点insatall 打包即可。

image.png

在target中可以看到生成的war包。

image.png

Nginx之负载均衡

负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。 —百度百科

1、修改Nginx配置

cd /usr/local/nginx
vim nginx.conf

添加:

upstream backend_tomcat{
     #服务分别指向不同的tomcat实例
     server 192.168.5.128:8080;
     server 192.168.1.232:8080;
    }
server{
     #监听 8083 端口
     listen       8083;
     server_name  localhost;
 
     location /{
     proxy_pass http://backend_tomcat;
    }
}

2、重载nginx配置

./nginx -s reload

我这里为了演示不同的效果,将输出内容更改为一个有很多—,一个没有;

image.png3、演示:

将项目打成war包,分别放入不同的tomcat的webapps目录下,启动tomcat即可。

CentOS之Tomcat 安装

官方镜像仓库:http://archive.apache.org/dist/tomcat/

1、下载

选择需要的版本,复制链接地址:http://archive.apache.org/dist/tomcat/tomcat-8/v8.5.9/bin/apache-tomcat-8.5.9.tar.gz

在仓库的bin目录下复制地址,不是src

我这里用wget下载,执行:wget http://archive.apache.org/dist/tomcat/tomcat-8/v8.5.9/bin/apache-tomcat-8.5.9.tar.gz

image.png

等待下载完成。。。。。。

2、解压

进入目录,然后解压:

cd /usr/src 
tar -zxvf apache-tomcat-8.5.9.tar.gz

3、查看JDK路径

echo $JAVA_HOME
echo $JRE_HOME

image.png

4、添加环境

cd apache-tomcat-8.5.9/bin/

image.png

vim setclasspth.sh 

添加下面两句:
export JAVA_HOME=/usr/local/java/jdk1.8.0_141
export JRE_HOME=/usr/local/java/jdk1.8.0_141/jre

image.png

然后保存

5、运行

执行 ./startup.sh   

image.png

启动完成,然后访问ip:8080 看到tomcat界面就算成功了。

image.png

如果没有访问成功,可能是防火墙的问题,关闭防火墙,或者添加规则。

Nginx之安装

环境:CentOS 7

编译环境安装:

安装make

 yum -y install gcc automake autoconf libtool make

安装g++

yum install gcc gcc-c++

正式开始安装:


1、选目录-这里选用 /usr/local/src

cd /usr/local/src

2、安装PCRE库

cd /usr/local/src
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.42.tar.gz 
tar -zxvf pcre-8.42.tar.gz
cd pcre-8.42
./configure
make
make install

依次执行以上命令即可;

我这里都是最新的版本,如果安装时提醒版本不正确,可以打开  ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre 查看最新版本号,替换即可;

image.png

3、安装zlib库

cd /usr/local/src
wget http://zlib.net/zlib-1.2.11.tar.gz
tar -zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure
make
make install

和2一样,依次执行上述命令;

查看最新版本号:http://zlib.net/

image.png4、安装ssl

cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.0.1t.tar.gz
tar -zxvf openssl-1.0.1t.tar.gz

最新版本号:https://www.openssl.org/source/

5、安装nginx

cd /usr/local/src
wget http://nginx.org/download/nginx-1.9.9.tar.gz
tar -zxvf nginx-1.9.9.tar.gz
cd nginx-1.9.9
 
./configure --sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--with-http_ssl_module \
--with-pcre=/usr/local/src/pcre-8.42 \
--with-zlib=/usr/local/src/zlib-1.2.11 \
--with-openssl=/usr/local/src/openssl-1.0.1t
 
make
make install

–with-pcre=/usr/local/src/pcre-8.42 指的是pcre-8.42 的源码路径
–with-zlib=/usr/local/src/zlib-1.2.11 指的是zlib-1.2.11 的源码路径

安装成功后,进入 /usr/local/nginx 可查看当前的目录

image.png

6、启动

确保80端口未被占用,然后执行 sudo /usr/local/nginx/nginx  即可启动nginx服务。

打开浏览器,访问ip就可以了。如果出现下面的字样就说明安装成功了。

image.png

Mybatis 多参数查询及where使用

背景:多维度查询,有可能都为空,也可以不为空。

<select id="queryBySomeParam" resultMap="BaseResultMap">
  select
  <include refid="Base_Column_List" />
  from tablename
  <where>
  <if test="paramA !=null and paramA.length()>0" >
     paramA=#{paramA,jdbcType=VARCHAR}
  </if>
  <if test="paramB !=null and paramB.length()>0">
   and paramB=#{paramB,jdbcType=VARCHAR}
  </if>
  <if ...>
  ...
  </if>
  </where>
  order by id desc
</select>

where会根据前面的参数自动判断and的省略,如果paramA为空,则自动省略and,即,执行数据库语句为:

select * from table where paramB = xxx

多参数传递,dao中需注入参数,即:

List<Entity> queryBySomeParam(@Param(value = "paramA") String paramA, 
            @Param(value = "paramB")String paramB ...);