技术标签: JAVA 过滤器 多次获取request参数 拦截器 springboot
先说一下过滤器和拦截器。
提前总结一下,我这里的过滤器和拦截器的使用:
filter: 目的就是可以以流的方式多次获取请求参数。
Interceptor: 对回调接口进行统一的验证签名。
回调接口都需要验证签名,而且签名规则一样,所以想拿到拦截器处理。
如果签名或者ip地址不符合条件,直接就返回了。而具体的接口只要专注业务处理,不需要验证签名了。
下面贴一下在springboot中的使用:
1. filter:
InterfaceFilter.java
package com.test.test.filter;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(urlPatterns = "/*", filterName = "InterfaceFilter")
public class InterfaceFilter implements Filter{
private static Logger log = LoggerFactory.getLogger(InterfaceFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try {
if ("POST".equals(req.getMethod().toUpperCase())) {
// 获取请求参数
byte[] bytes = IOUtils.toByteArray(request.getInputStream());
String params = new String(bytes, req.getCharacterEncoding());
ThreadCache.setPostRequestParams(params);
log.info("filer-post请求参数:[params={}]", params);
} else {
log.info("非post请求");
}
chain.doFilter(request, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
@Override
public void destroy() {
}
}
ThreadCache.java:
package com.test.test.filter;
public class ThreadCache {
// ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数
private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();
public static String getPostRequestParams(){
return threadLocal.get();
}
public static void setPostRequestParams(String postRequestParams){
threadLocal.set(postRequestParams);
}
public static void removePostRequestParams(){
threadLocal.remove();
}
}
说一下WebFilter注解。
urlPatterns指的是过滤哪个路径。跟在xml中配置是一样的作用。推荐一篇多次获取request参数的博客:
https://www.cnblogs.com/endstart/p/6196807.html
2. Interceptor:
PlatformInterceptor.java:
package com.test.test.interceptor;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.constants.IMsgEnum;
import com.test.test.filter.ThreadCache;
import com.test.test.resp.BaseResp;
import com.test.test.security.SignCheck;
import com.test.test.utils.DESTools;
import com.test.test.utils.JsonUtil;
import com.test.test.utils.LogUtils;
import com.test.test.utils.NetworkUtil;
import com.test.test.utils.ReflectUtil;
/**
* ClassName: PlatformInterceptor date: 2015年12月30日 下午2:13:24 Description: 拦截器
*
* @author xiaozhan
* @version
* @since JDK 1.8
*/
@Component
public class PlatformInterceptor implements HandlerInterceptor {
private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
@Autowired
private SignCheck signCheck;
@Autowired
private ConfigProperties configProperties;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info(LogUtils.getRequestLog(request));
// 获取自定义注解
String allowOrigin = null;
String servletPath = request.getServletPath();
boolean isDeprecated = false;
BaseResp baseResp = new BaseResp();
ServletOutputStream out = response.getOutputStream();
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Deprecated deprecated = handlerMethod.getMethodAnnotation(Deprecated.class);
if (deprecated != null) {
isDeprecated = true;
}
}
String method = request.getMethod();
if (!method.equals(RequestMethod.POST.name())) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
String clientIp = NetworkUtil.getIpAddress(request);
logger.info("------ client Ip is ---》" + clientIp);
// 判断是否是ip白名单
if (!signCheck.checkIpAddress(clientIp)) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
// 验证签名
String params = ThreadCache.getPostRequestParams();
logger.info("interceptor-post请求参数:[params={}]" + params);
Map<String, Object> map = ReflectUtil.getDecodeParamMap(params);
String sign = (String) map.get("sign");
if (map.containsKey("sign")) {
map.remove("sign");
}
// 签名校验
if (!SignCheck.checkSign(map, sign, configProperties.getPrivateKey())) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_SIGN_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_SIGN_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_SIGN_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
try {
if (isDeprecated) {
logger.error(LogUtils.getCommLog(String.format("该接口已停止使用,%s", servletPath)));
}
} catch (Exception e) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAMETER_INVALID.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAMETER_INVALID.getMsgText());
logger.info("----- " + IMsgEnum.PARAMETER_INVALID.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
可以针对某些具体的请求进行拦截。我这里没做限制,所有的请求都走。如果想拦截 特定的请求,判断一下request.getContextPath()是否包含某个路径。(后续更新)
我这里用到拦截器的作用是对回调接口进行统一的验证签名。分享一下用的工具类:ip和签名校验:
signCheck.java:
package com.test.test.security;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.interceptor.PlatformInterceptor;
import com.test.test.utils.Signature;
import org.springframework.stereotype.Service;
/**
* @author gmwang E-mail:
* @version 创建时间:2018年3月1日 上午10:35:47
* 类说明 :校验签名和ip
*/
@Service(value="signCheck")
public class SignCheck{
private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
@Autowired
private ConfigProperties configProperties;
@Bean
public SignCheck getSignCheck(){
return new SignCheck();
}
/**
* 校验签名
* @Description:
* @author:
* @throws IllegalAccessException
* @time:2018年3月1日 上午10:38:09
*/
public static Boolean checkSign(Map params, String sign,String privateKey) throws IllegalAccessException {
if(StringUtils.isBlank(sign)) {
logger.info("*********************sign is null*********************");
return false;
}else {
String signAfter = Signature.getSign(params,privateKey);
System.out.println("sign:"+sign);
System.out.println("signAfter:"+signAfter);
if(!sign.equals(signAfter)) {
logger.info("*********************sign is not equal signAfter*********************");
return false;
}
}
return true;
}
/**
* 校验ip
* @Description:
* @author:
* @throws IllegalAccessException
* @time:2018年3月1日 上午10:38:09
*/
public Boolean checkIpAddress(String ip) throws IllegalAccessException {
String ipWhite = configProperties.getRequestUrl();
System.out.println(ipWhite);
String[] ipWhiteArray = ipWhite.split(",");
List<String> ipWhiteList = Arrays.asList(ipWhiteArray);
if(!ipWhiteList.contains(ip)) {
logger.info("*********************ip is not in ipWhiteList*********************");
return false;
}
return true;
}
}
获取ip地址工具类:NetworkUtil.java:
package com.test.test.utils;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
/**
* 常用获取客户端信息的工具
*
*/
public final class NetworkUtil {
/**
* Logger for this class
*/
private static Logger logger = Logger.getLogger(NetworkUtil.class);
/**
* 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
*
* @param request
* @return
* @throws IOException
*/
public final static String getIpAddress(HttpServletRequest request) throws IOException {
// 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
String ip = request.getHeader("X-Forwarded-For");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip);
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip);
}
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
}
}
加密解密工具类:Signature.java:
package com.test.test.utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
/**
* User:
* Date: 2015/8/26
* Time: 15:23
*/
public class Signature {
/**
* 签名算法
* @param o 要参与签名的数据对象
* @return 签名
* @throws IllegalAccessException
*规则:签名,将筛选的参数按照第一个字符的键值ASCII码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推,形成key=value& * skey的字符串MD5加密; (必填)
*/
public static String getSign(Object o) throws IllegalAccessException {
ArrayList<String> list = new ArrayList<String>();
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
if (f.get(o) != null && f.get(o) != "") {
list.add(f.getName() + "=" + f.get(o) + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
System.out.println(result);
result = MD5Util.MD5Encode(result).toUpperCase();
System.out.println(result);
return result;
}
public static String getSign(Map<String,Object> map,String privateKey){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(entry.getValue()!=""){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
sb.append(privateKey);
String result = sb.toString();
System.out.println(result);
result = MD5Util.MD5Encode(result).toUpperCase();
return result;
}
public static void main(String[] args) {
/*
* */
Map<String,Object> map=new HashMap();
map.put("uuid","PC0000000056");
String result= getSign(map,"aaaaa!aaa");
System.out.println(result);
map.put("sign", result);//sign
DESTools desTools = new DESTools();
String s = JSONObject.toJSONString(map);
System.out.println(s);
String param= desTools.getEncString(s);
String str= HttpUtil.doPost("http://localhost:8111/test/test", param);
System.out.println(str);
}
}
DESTools.java:
package com.test.test.utils;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DESTools {
public static DESTools instance;
public static DESTools getInstace()
{
if(instance == null)
{
instance = new DESTools();
}
return instance;
}
Key key;
/**
* 密钥
*/
private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7,
(byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd,
(byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28,
0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 };
public DESTools() {
setKey(BOSS_SECRET_KEY);
}
/**
* 根据参数生成KEY
*/
public void setKey(byte[] strKey) {
try {
DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY);
SecretKeyFactory keyFactory;
keyFactory = SecretKeyFactory.getInstance("DES");
this.key = keyFactory.generateSecret(dks);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
}
}
/**
* 加密String明文输入,String密文输出
*/
public String getEncString(String strMing) {
byte[] byteMi = null;
byte[] byteMing = null;
String strMi = "";
Base64 base64en = new Base64();
try {
byteMing = strMing.getBytes("UTF8");
byteMi = this.getEncCode(byteMing);
strMi = base64en.encodeAsString(byteMi);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
base64en = null;
byteMing = null;
byteMi = null;
}
return strMi;
}
/**
* 解密 以String密文输入,String明文输出
* @param strMi
* @return
*/
public String getDesString(String strMi) {
Base64 base64De = new Base64();
byte[] byteMing = null;
byte[] byteMi = null;
String strMing = "";
try {
byteMi = base64De.decode(strMi);
byteMing = this.getDesCode(byteMi);
strMing = new String(byteMing, "UTF8");
} catch (Exception e) {
throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);
} finally {
base64De = null;
byteMing = null;
byteMi = null;
}
return strMing;
}
/**
* 加密以byte[]明文输入,byte[]密文输出
* @param byteS
* @return
*/
private byte[] getEncCode(byte[] byteS) {
byte[] byteFina = null;
Cipher cipher;
try {
cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byteFina = cipher.doFinal(byteS);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
cipher = null;
}
return byteFina;
}
/**
* 解密以byte[]密文输入,以byte[]明文输出
* @param byteD
* @return
*/
private byte[] getDesCode(byte[] byteD) {
Cipher cipher;
byte[] byteFina = null;
try {
cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byteFina = cipher.doFinal(byteD);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
cipher = null;
}
return byteFina;
}
}
获取yml文件的值:
ConfigProperties.java:
package com.test.test.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@Component
public class ConfigProperties {
@Value("${test.test.privateKey}")
private String privateKey;
@Value("${test.test.requestUrl}")
private String requestUrl;
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl;
}
}
yml文件如图:
2018-07-08 更新:
springboot 2.x 过滤器和拦截器 放行某个路径(静态资源):
package xxx.xxxx.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import xxx.xxxx.interceptor.PlatformInterceptor;
@EnableWebMvc
@Configuration
@Component
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
PlatformInterceptor passportInterceptor;
/**
* 处理拦截器 拦截路径(暂时无效)
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
registry.addInterceptor(passportInterceptor).addPathPatterns("/**")
.excludePathPatterns("notify","/static/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 处理过滤器 静态资源放行
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
/**
* 利用fastjson替换掉jackson,且解决中文乱码问题
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
//处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
fastConverter.setFastJsonConfig(fastJsonConfig);
converters.add(fastConverter);
WebMvcConfigurer.super.configureMessageConverters(converters);
}
}
文章浏览阅读172次,点赞9次,收藏4次。笔记本更改物理地址,无法更改_笔记本mac地址不能改
文章浏览阅读186次。多进程编程13.1 fork系统调用13.2exec系列系统调用13.3 处理僵尸进程13.4 管道13.5 信号量13.5.1 信号量原语13.5.2 semget系统调用13.5.3 semop系统调用13.5.4 semctl系统调用13.5.5 特殊键值IPC_PRIVATE13.6 共享内存13.6.1 shmget系统调用13.6.2 shmat和shmdt系统调用13.6.3 shmctl系统调用13.6.4 共享内存的POSIX方法13.6.5 共享内存实例13.7 消息队列13.7.1 m_linux高性能服务器编程 13.9
文章浏览阅读1.2k次,点赞27次,收藏23次。Atomic类位于java.util.concurrent.atomic包下,它们利用CAS(Compare-And-Swap)操作来保证线程安全性,而无需使用传统的锁机制。这些类提供了一种轻量级的同步机制,适用于多线程环境下对共享变量的高效更新。
文章浏览阅读4.7k次,点赞10次,收藏30次。今天看见数学院群里有人在讨论一道有意思的题目,题意好像是这样的:在一个1010的正方形里最多可以放多少个半径为1圆?有大佬在知乎里找到了1010的正方形能放多少个直径为1的圆,那么最优的放置方法如下:从图中可以看出,并不是每一排放10个,放10排是最优的。因为这样会造成中间的空隙很大。可以看出更优的放置方法是:交错着放,即(图中从下往上看):第一排放10个,第二排放9个,第三排放10个。第二排..._怎么计算矩形里面可以放入最多数量的圆
文章浏览阅读1.4w次,点赞5次,收藏20次。TensorflowTensorFlow 是谷歌开源的机器学习框架,相对于其它现有框架来说,其具有比较好的扩展性,但是也牺牲了它的速度。下面介绍Tensorflow 的基本使用:1, tensorflow 基本操作:import tensorflow as tfimport numpy as np乘法:a = tf.placeholder("float") # 创建符号变量b = tf.plac_tensoflow使用
文章浏览阅读2.3w次,点赞5次,收藏36次。俗话说:工欲善其事必先利其器,那么在一切开始知之前就先利下你的器吧,说白了就是把该装的软件先装好了。。。_vs2013安装布部署插件
文章浏览阅读2.2k次。2019独角兽企业重金招聘Python工程师标准>>> ..._齐齐哈尔奇闻科技有限责任公司 网银支付插件
文章浏览阅读1.2k次。原文链接:https://blog.csdn.net/abcnull/java/article/details/89001642代理模式Fiddler 的代理模式有流模式和缓冲模式,其中流模式是一种实时通信模式,请求之后实时的返回,更接近浏览器真实行为,另外一种是缓冲模式,等所有请求到了再一起返回,可以来控制最后的服务器响应,实际中我们可以根据具体场景选用不同代理模式,fiddler 默认缓冲模式,这里可改变菜单栏file这里与文件导入导出加载有关Capture Traffic:默认勾_fiddler说明fiddler结构每项什么意思
文章浏览阅读925次。通过经纬度坐标计算距离的方法(经纬度距离计算)最近在网上搜索“通过经纬度坐标计算距离的方法”,发现网上大部分都是如下的代码:#define PI 3.14159265static double Rc = 6378137; // 赤道半径static double Rj = 6356725; // 极半径class JWD{public:double m_Longitude, m_Latitud..._qt中知道两点经纬度求距离和在坐标系上显示点位置
文章浏览阅读333次。下方注释的是爬取图片的爬虫爬取的图片集放在同级目录image文件夹下,每一个像素点都是一个图片import osimport sysimport timeimport mathimport numpy as npfrom PIL import Image, ImageOpsfrom multiprocessing import Poolfrom colorsys import rgb_to_hsv..._def mosaic(imgpath1, imgpath2): img=image.open(imgpath1) width,height=img.si
文章浏览阅读1k次。在不ping任何服务器的情况下,无法获得下载/上传速度 . 由于您的服务器不支持ping,您可以使用第三方pinging站点 .使用JSpeedTest库,您可以轻松完成 . 您可以在此库中找到一些所需的功能 . 如速度测试下载速度测试上传下载/上传进度监控可配置主机名/端口/ uri(FTP的用户名和密码)可配置的套接字超时和块大小配置上传文件存储摇篮:compile 'fr.bmartel:j..._androidjspeedtest库使用
文章浏览阅读196次,点赞7次,收藏5次。解决方案ImportError: cannot import name 'BertTokenizerFast' from 'transformers'_cannot import barttokenizer