任务调度中心xxl-job对外接口使用
xxl-job主要分为调度中心和执行器提供了图像化界面,操作简单上手快,基本实现定时任务自动执行,同时可以针对任务日志进行查看。具体xxl-job可以再github上下载:https://github.com/xuxueli/xxl-job。
本文主要描述xxl-job的接口调用
pom.xml引入
<!--针对自己项目的xxl-job-core进行引入即可-->
<dependency>
<groupId>com.test</groupId>
<artifactId>xxl-job-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--org.apache.commons.httpclient-->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
application.yml配置信息
xxl:
job:
admin:
# xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
# xxl-job-admin 启动地址
addresses: http://192.168.1.59:7000/xxl-job-admin
# xxl-job, access token
accessToken:
executor:
# xxl-job executor appname 手动配置的客户端名称
appname: xxl-job-executor-test
# xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
address:
# xxl-job executor server-info 可以自动分配地址进行注册
ip:
port: 9985
# xxl-job executor log-path
logpath: logs/applogs/xxl-job/jobhandler
# xxl-job executor log-retention-days
logretentiondays: 30
controller层代码
package com.controller; import com.alibaba.fastjson.JSONObject;
import com.util.TimeUtil;
import com.util.results.Resp;
import com.hywx.gw.loadservice.util.XxlJobUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import java.io.IOException;
import java.util.Date; /**
* @ClassName: TestSaveXxlController
* @Description:
* @Author LXYuuuuu
* @Date 2020/6/29 15:38
*/
@RestController
@RequestMapping("/Test")
public class TestXxlJobController {
private static final Logger LOGGER = LoggerFactory.getLogger(TestXxlJobController.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String executorAppname; @ApiOperation(value = "添加jobInfo并启动", httpMethod = "GET")
@GetMapping
public Resp saveXxl() {
//查询列表数据
try {
JSONObject requestInfo = new JSONObject();
// 执行器主键ID
requestInfo.put("jobGroup", 2);
// 任务执行CRON表达式
long etime1 = System.currentTimeMillis() + 1 * 60 * 1000;//延时函数,单位毫秒,这里是延时了1分钟
String date = TimeUtil.getCron(new Date(etime1));
System.out.println(date);
// requestInfo.put("jobCron","0 0/1 * * * ?");
requestInfo.put("jobCron", date);
// 任务描述
requestInfo.put("jobDesc", "xxxJob"); // 负责人
requestInfo.put("author", "admin");
// 报警邮件
requestInfo.put("alarmEmail", "xxx@satcloud.com.cn"); // 执行器路由策略
requestInfo.put("executorRouteStrategy", "FIRST");
// 执行器,任务Handler名称
requestInfo.put("executorHandler", "xxxJobHandler");
// todo 执行器,任务参数
requestInfo.put("executorParam", "测试202006300943");
// 阻塞处理策略
requestInfo.put("executorBlockStrategy", "SERIAL_EXECUTION");
// 任务执行超时时间,单位秒
requestInfo.put("executorTimeout", 0);
// 失败重试次数
requestInfo.put("executorFailRetryCount", 1);
// GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
requestInfo.put("glueType", "BEAN");
// GLUE备注
requestInfo.put("glueRemark", "GLUE代码初始化"); // 调度状态:0-停止,1-运行
requestInfo.put("triggerStatus", 0);
// 上次调度时间
requestInfo.put("triggerLastTime", 0);
// 下次调度时间
requestInfo.put("triggerNextTime", 0);
// requestInfo.put("cronGen_display","0 0/1 * * * ?");
JSONObject response = XxlJobUtil.addJob(adminAddresses, requestInfo);
if (response.containsKey("code") && 200 == (Integer) response.get("code")) {
//修改任务参数 把id放入
// 执行器主键ID
requestInfo.put("executorParam", "JobId=" + response.get("content") + ";测试202006300943");
requestInfo.put("id", Integer.valueOf(response.get("content").toString()));
JSONObject responseUpdate = XxlJobUtil.updateJob(adminAddresses, requestInfo);
if (responseUpdate.containsKey("code") && 200 == (Integer) responseUpdate.get("code")) {
//加入任务成功之后直接启动
JSONObject responseStart = XxlJobUtil.startJob(adminAddresses, Integer.valueOf(response.get("content").toString()));
if (responseStart.containsKey("code") && 200 == (Integer) responseStart.get("code")) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-start接口失败!");
}
} else {
throw new Exception("调用xxl-job-admin-update接口失败!");
}
} else {
throw new Exception("调用xxl-job-admin-add接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
}
} /**
* 删除任务
*
* @param id
* @return
* @throws IOException
*/
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public Resp delete(int id) {
try {
JSONObject response = XxlJobUtil.deleteJob(adminAddresses, id);
if (response.containsKey("code") && 200 == (Integer) response.get("code")) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-delete接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
} } /**
* 开始任务
*
* @param id
* @return
* @throws IOException
*/
@RequestMapping(value = "/start", method = RequestMethod.GET)
public Resp start(int id) {
try {
JSONObject response = XxlJobUtil.startJob(adminAddresses, id);
if (response.containsKey("code") && 200 == (Integer) response.get("code")) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-start接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
} } /**
* 挂起任务
*
* @param id
* @return
* @throws IOException
*/
@RequestMapping(value = "/stop", method = RequestMethod.GET)
public Resp stop(int id) {
try {
JSONObject response = XxlJobUtil.stopJob(adminAddresses, id);
if (response.containsKey("code") && 200 == (Integer) response.get("code")) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-stop接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
}
} /**
* 登陆
*
* @param userName
* @param password
* @return
* @throws IOException
*/
@RequestMapping(value = "/login", method = RequestMethod.GET)
public Resp login(String userName, String password) {
try {
String cookie = XxlJobUtil.login(adminAddresses, userName, password);
if (StringUtils.isNotBlank(cookie)) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-login接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
}
}
/**
* 根据xxl-appname获取对应id
*
* @return
* @throws IOException
*/
@RequestMapping(value = "/getAppNameIdByAppname", method = RequestMethod.GET)
public Resp getAppNameIdByAppname() {
try {
JSONObject response = XxlJobUtil.getAppNameIdByAppname(adminAddresses,executorAppname);
if (response.containsKey("code") && 200 == (Integer) response.get("code")) {
return Resp.getInstantiationSuccess("成功", null, null);
} else {
throw new Exception("调用xxl-job-admin-getAppNameIdByAppname接口失败!");
}
} catch (Exception e) {
return Resp.getInstantiationError("失败" + e.getMessage(), null, null);
}
}
}
XxlJobUtil 工具类
package com.util; import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; /**
* @ClassName: ApiUtil
* @Description:
* @Author LXYuuuuu
* @Date 2020/6/30 9:47
*/
public class XxlJobUtil { public static Logger logger = LoggerFactory.getLogger(XxlJobUtil.class); private static String cookie=""; /**
* 新增/编辑任务
* @param url
* @param requestInfo
* @return
* @throws HttpException
* @throws IOException
*/
public static JSONObject addJob(String url, JSONObject requestInfo) throws HttpException, IOException {
String path = "/jobinfo/add";
String targetUrl = url + path;
HttpClient httpClient = new HttpClient();
PostMethod post = new PostMethod(targetUrl);
RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), "application/json", "utf-8");
post.setRequestEntity(requestEntity);
httpClient.executeMethod(post);
JSONObject result = new JSONObject();
result = getJsonObject(post, result);
return result;
} public static JSONObject updateJob(String url, JSONObject requestInfo) throws HttpException, IOException {
String path = "/jobinfo/update";
String targetUrl = url + path;
HttpClient httpClient = new HttpClient();
PostMethod post = new PostMethod(targetUrl);
RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), "application/json", "utf-8");
post.setRequestEntity(requestEntity);
httpClient.executeMethod(post);
JSONObject result = new JSONObject();
result = getJsonObject(post, result);
return result;
} /**
* 删除任务
* @param url
* @param id
* @return
* @throws HttpException
* @throws IOException
*/
public static JSONObject deleteJob(String url,int id) throws HttpException, IOException {
String path = "/jobinfo/delete?id="+id;
return doGet(url,path);
} /**
* 开始任务
* @param url
* @param id
* @return
* @throws HttpException
* @throws IOException
*/
public static JSONObject startJob(String url,int id) throws HttpException, IOException {
String path = "/jobinfo/start?id="+id;
return doGet(url,path);
} /**
* 停止任务
* @param url
* @param id
* @return
* @throws HttpException
* @throws IOException
*/
public static JSONObject stopJob(String url,int id) throws HttpException, IOException {
String path = "/jobinfo/stop?id="+id;
return doGet(url,path);
} /**
* 根据xxl-appname获取对应id
* @param url
* @param appnameParam
* @return
* @throws HttpException
* @throws IOException
*/
public static JSONObject getAppNameIdByAppname(String url,String appnameParam) throws HttpException, IOException {
String path = "/jobgroup/getAppNameIdByAppname?appnameParam="+appnameParam;
return doGet(url,path);
} public static JSONObject doGet(String url,String path) throws HttpException, IOException {
String targetUrl = url + path;
HttpClient httpClient = new HttpClient();
HttpMethod get = new GetMethod(targetUrl);
get.setRequestHeader("cookie", cookie);
httpClient.executeMethod(get);
JSONObject result = new JSONObject();
result = getJsonObject(get, result);
return result;
} private static JSONObject getJsonObject(HttpMethod get, JSONObject result) throws IOException {
InputStream inputStream = get.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer stringBuffer = new StringBuffer();
String str = "";
while ((str = br.readLine()) != null) {
stringBuffer.append(str);
}
if (get.getStatusCode() == 200) {
/**
* 使用此方式会出现
* Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
* 异常
* String responseBodyAsString = get.getResponseBodyAsString();
* result = JSONObject.parseObject(responseBodyAsString);*/
result = JSONObject.parseObject(stringBuffer.toString());
} else {
try {
// result = JSONObject.parseObject(get.getResponseBodyAsString());
result = JSONObject.parseObject(stringBuffer.toString());
} catch (Exception e) {
result.put("error", stringBuffer.toString());
}
}
return result;
} public static String login(String url, String userName, String password) throws HttpException, IOException {
String path = "/jobinfo/login?userName="+userName+"&password="+password;
String targetUrl = url + path;
HttpClient httpClient = new HttpClient();
HttpMethod get = new GetMethod(targetUrl);
httpClient.executeMethod(get);
if (get.getStatusCode() == 200) {
Cookie[] cookies = httpClient.getState().getCookies();
StringBuffer tmpcookies = new StringBuffer();
for (Cookie c : cookies) {
tmpcookies.append(c.toString() + ";");
}
cookie = tmpcookies.toString();
} else {
try {
cookie = "";
} catch (Exception e) {
cookie="";
}
}
return cookie;
}
}
TimeUtil 工具类
public class TimeUtil {
/***
* convert Date to cron ,eg. "0 07 10 15 1 ? 2016"
* @param date : 时间点
* @return
*/
public static String getCron(Date date) {
String dateFormat = "ss mm HH dd MM ? yyyy";
return formatDateByPattern(date, dateFormat);
}
}
Resp返回类
/**
* @program:
* @description: 前端传递信息封装
* @author: LXYuuuuu
* @create: 2020-06-25 09:27
**/
public class Resp {
/** 用于状态码 */
public static final int SUCCESS = 200;
public static final int ERROR = 404;
public static final int TOKENERROR=1001;
public static final int DATACOLLISION=1002; /** 数据类型 */
public static final String LIST = "LIST";
public static final String SINGLE = "SINGLE";
public static final String MAP = "MAP";
public static final String PAGE = "PAGE";
public static final String STRING = "STRING";
public static final String JSONSTRING = "JSONSTRING"; /** 操作简单提示 */
public static final String SUCCESS_INFO = "操作成功";
public static final String ERROR_INFO = "操作失败";
/** 状态码 */
private int code;
/** 返回提示信息 */
private String message;
/** 数据类型 */
private String dataType;
/** 返回对象 */
private Object respBody; private Resp() {} /**
* @Description: 返回实例化Resp
* @return: Resp
*/
public static Resp getInstantiation() {
return new Resp();
} /**
* @Description: 返回实例化Resp
* @Param: @param code 状态码
* @Param: @param message 返回提示信息
* @Param: @param dataType 数据类型
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiation(int code,String message,String dataType,Object respBody) {
Resp resp = getInstantiation();
resp.setCode(code);
resp.setMessage(message);
resp.setDataType(dataType);
resp.setRespBody(respBody);
return resp;
} /**
*
* @Description: 返回状态为Success的实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param dataType 数据类型
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccess(String message,String dataType,Object respBody) {
return getInstantiation(SUCCESS, message, dataType, respBody);
}
public static Resp getInstantiationTokenError(String message,String dataType,Object respBody) {
return getInstantiation(TOKENERROR, message, dataType, respBody);
}
public static Resp getInstantiationDATACOLLISIONError(String message,String dataType,Object respBody) {
return getInstantiation(DATACOLLISION, message, dataType, respBody);
}
/**
* @Description: 返回状态为Success的String类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccessString(String message,Object respBody) {
return getInstantiation(SUCCESS, message, STRING, respBody);
}
/**
*
* @author: zy
* @Description: 返回状态为Success的List类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccessList(String message,Object respBody) {
return getInstantiation(SUCCESS, message, LIST, respBody);
} /**
* @Description: 返回状态为Success的Map类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccessMap(String message,Object respBody) {
return getInstantiation(SUCCESS, message, MAP, respBody);
}
/**
* @Description: 返回状态为Success的Page类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccessPage(String message,Object respBody) {
return getInstantiation(SUCCESS, message, PAGE, respBody);
} /**
* @Description: 返回状态为Success的Page类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationSuccessJsonString(String message,Object respBody) {
return getInstantiation(SUCCESS, message, JSONSTRING, respBody);
} /**
* @Description: 返回状态为Error的实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param dataType 数据类型
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationError(String message,String dataType,Object respBody) {
return getInstantiation(ERROR, message, dataType, respBody);
}
/**
* @Description: 返回状态为Error的String类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationErrorString(String message,Object respBody) {
return getInstantiation(ERROR, message, STRING, respBody);
}
/**
* @Description: 返回状态为Error的List类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationErrorList(String message,Object respBody) {
return getInstantiation(ERROR, message, LIST, respBody);
}
/**
* @Description: 返回状态为Error的Map类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationErrorMap(String message,Object respBody) {
return getInstantiation(ERROR, message, MAP, respBody);
}
/**
* @Description: 返回状态为Error的Page类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationErrorPage(String message,Object respBody) {
return getInstantiation(ERROR, message, PAGE, respBody);
}
/**
* @Description: 返回状态为Error的JsonString类型实例化Resp
* @Param: @param message 返回提示信息
* @Param: @param respBody 返回对象
* @return: Resp
*/
public static Resp getInstantiationErrorJsonString(String message,Object respBody) {
return getInstantiation(ERROR, message, JSONSTRING, respBody);
} public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
} public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
} public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
} public Object getRespBody() {
return respBody;
}
public void setRespBody(Object respBody) {
this.respBody = respBody;
} /**
* @Description: 判断是否成功
* @return: boolean true:成功,false:错误
*/
public boolean isSuccess() {
return this.code==SUCCESS;
} }
到此,对外新增、编辑、删除、启动、挂起等接口就已经写好了。
任务调度中心xxl-job对外接口使用的更多相关文章
- 基于Spring AOP实现对外接口的耗时监控
AOP是Spring的核心,Spring不但自身对多种框架的集成是基于AOP,并且以非常方便的形式暴露给普通使用者.以前用AOP不多,主要是因为它以横截面的方式插入到主流程中,担心导致主流程代码不够清 ...
- Spring boot下,集成任务调度中心(XXL-JOB)
一.使用背景 目前项目中,采用的是微服务框架,由于在微服务中,存在需要定时的任务.但如果定时任务维护在每个微服务下,当微服务部署多个实例的情况下,会出现定事任务多次执行的情况.并且在解决问题的基础上, ...
- 利用Swagger2自动生成对外接口的文档
一直以来做对外的接口文档都比较原始,基本上都是手写的文档传来传去,最近发现了一个新玩具,可以在接口上省去不少麻烦. swagger是一款方便展示的API文档框架.它可以将接口的类型最全面的展示给对方开 ...
- XXL-JOB原理--任务调度中心任务管理
XXL-JOB原理--任务调度中心任务管理 https://blog.csdn.net/qq924862077/article/details/82713758
- python笔记44-HTTP对外接口sign签名
前言 一般公司对外的接口都会用到sign签名,对不同的客户提供不同的apikey ,这样可以提高接口请求的安全性,避免被人抓包后乱请求. sign签名是一种很常见的方式 sign签名 签名参数sign ...
- EffectiveC#03--用委托表示回调,用事件定义对外接口
1.回调的场景:我给了儿子一个任务且他可以报告状态来(重复的)打断我.而我在等待他完成任务的每一个部份时不用阻塞我自己的进程.他可以在有重要(或者事件)状态报告时,可以定时的打断我,或者向我询求帮助 ...
- 【JEECG技术文档】JEECG平台对外接口JWT应用文档V3.7.2
一. 接口方式 接口调用采用http协议,rest请求方式: 二. 接口安全 接口安全采用Json web token (JWT)机制,基于token的鉴权机制. 1. 机制说明 基于token的鉴权 ...
- 快速开发框架(FDMS)新增1000个对外接口都不须要手写一行代码
一个大型系统难免会跟其它系统有数据交换,这里就要提供数据接口给外部系统. 曾经在一家智能终端设备的公司上班.那段时间的主要工作就是写接口.接口须要与手机.手持设备.系统管理软件等进行数据交换.总结了一 ...
- python接口自动化:对外接口sign签名
签名参数sign生成的方法: 在接口开发过程中,一般通过时间戳+sign作为密匙加密传输 实现代码如下: #python实现sign签名 import hashlib,time class sign: ...
随机推荐
- weblogic之高级进阶JMS的应用
不仅Activemq提供的jms服务,Weblogic也提供了jms服务,很多项目是部署在Weblogic中,使用其提供的jms服务也是很多企业的选择,一直没亲手试过,今天试了下,遇到的小问题还挺多, ...
- android activity状态的保存
今天接到一个电面,途中面试官问到一个问题,如果一个activity在后台的时候,因为内存不足可能被杀死,在这之前如果想保存其中的状态数据,比如说客户填的一些信息之类的,该在哪个方法中进行. onSav ...
- django drf 10大请求序列化方法
## 整体单改 路由层.模型层.序列化层不需要做修改,只需要处理视图层:views.py ```python"""1) 单整体改,说明前台要提供修改的数据,那么数据就需要 ...
- vue全家桶(2.6)
3.9.滚动行为 设置滚动行为的作用是导航到新路由时,让页面滚动到你想要的位置. const router = new VueRouter({ routes: [...], scrollBehavio ...
- 浅谈pyautogui模块
pyautogui模块 PyAutoGUI--让所有GUI都自动化 安装代码: pip install pyautogui 目的 PyAutoGUI是一个纯Python的GUI自动化工具,其目的是可以 ...
- Python3笔记002 - 1.2 搭建python开发环境
第1章 认识python 1.2 搭建python开发环境 1.2.1 python开发环境概述 python开发环境常见的操作系统: Windows Mac OS Linux 1.2.2 安装pyt ...
- 听说你还没学Spring就被源码编译劝退了?30+张图带你玩转Spring编译
源码学习第一步,Spring源码编译 之所以写这么一篇文章是因为群里的小伙伴在编译源码时碰到了问题,再加上笔者自身正准备做一个源码的注释版本,恰好也需要重新编译一份代码,至于为什么要将源码编译到本地就 ...
- Html5标签——Html5新增标签的含义和使用
HTML 5 是一个新的网络标准,目标在于取代现有的 HTML 4.01, XHTML 1.0 and DOM Level 2 HTML 标准.它希望能够减少浏览器对于需要插件的丰富性网络应用服务(p ...
- NOIP 2016 洛谷 P2827 蚯蚓 题解
题目传送门 展开 题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手 ...
- scrapy爬取海量数据并保存在MongoDB和MySQL数据库中
前言 一般我们都会将数据爬取下来保存在临时文件或者控制台直接输出,但对于超大规模数据的快速读写,高并发场景的访问,用数据库管理无疑是不二之选.首先简单描述一下MySQL和MongoDB的区别:MySQ ...