杂七杂八~~
文章目录
- 1.根据经纬度判断距离
- 2.判断某一时间是否在一个时间区间内
- 3.计算日期为星期几
- 4.判断今天是否超过某个日期
- 5.计算两个日期的天数间隔
- 6.日期格式的转换
- 7.计算当前时间与某个时间点的距离
- 8.二维码生成
- 9.微信小程序消息推送
- 10.AOP+注解实现日志入参出参打印
- 11.JSON格式的转换
- 12.通过地址获取经纬度(高德API)
1.根据经纬度判断距离
/*** 计算距离* @param lng 经度* @param lat 纬度* @return*/private double meter(BigDecimal lng1, BigDecimal lat1, BigDecimal lng, BigDecimal lat){double radiansAX = Math.toRadians(lng.doubleValue()); // 数据库经弧度double radiansAY = Math.toRadians(lat.doubleValue()); // 数据库纬弧度double radiansBX = Math.toRadians(lng1.doubleValue()); // 传入经弧度double radiansBY = Math.toRadians(lat1.doubleValue()); // 传入纬弧度double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX)+ Math.sin(radiansAY) * Math.sin(radiansBY);double acos = Math.acos(cos); // 反余弦值return (6371000 * acos);}
SQL函数
2.判断某一时间是否在一个时间区间内
/**** @param sourceTime* 时间区间,半闭合,如[10:00-20:00)* @param curTime* 需要判断的时间 如10:00* @return* @throws IllegalArgumentException*/public static boolean isInTime(String sourceTime, String curTime) {if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);}if (curTime == null || !curTime.contains(":")) {throw new IllegalArgumentException("Illegal Argument arg:" + curTime);}String[] args = sourceTime.split("-");SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");try {long now = sdf.parse(curTime).getTime();long start = sdf.parse(args[0]).getTime();long end = sdf.parse(args[1]).getTime();if (args[1].equals("00:00")) {args[1] = "24:00";}if (end < start) {if (now >= end && now < start) {return false;} else {return true;}}else {if (now >= start && now < end) {return true;} else {return false;}}} catch (ParseException e) {e.printStackTrace();throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);}}
3.计算日期为星期几
public static Integer getWeek(String date) {String[] split = date.split("-");int year = Integer.parseInt(split[0]);int month = Integer.parseInt(split[1]);int day = Integer.parseInt(split[2]);boolean leap=year%400==0||year%100!=0&&year%4==0; //判断当年是否为闰年int total=year-1980+(year-1980+3)/4;//前几年的天数累积量for(int i=month-1;i>0;i--){switch(i){case 1:case 3:case 5:case 7:case 8:case 10:total+=31;break;case 4:case 6:case 9:case 11:total+=30;break;case 2:total+=leap?29:28;}}total+=day;int week=1;week=(week+total)%7;return week;}
4.判断今天是否超过某个日期
public static boolean afterDate(Date date){String format = cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd");//把String转为LocalDateLocalDate localTime=LocalDate.parse(format,DateTimeFormatter.ofPattern("yyyy-MM-dd"));//判断当前日期是否大于指定日期return LocalDate.now().isAfter(localTime);}
5.计算两个日期的天数间隔
public static Long dayGap(Date start,Date end) throws ParseException {DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//Date start = df.parse(df.format(new Date()));Long startTime = start.getTime();Long endTime = end.getTime();Long num=endTime-startTime;// System.out.println("相差天数为:"+num/24/60/60/1000);return num/24/60/60/1000;}
6.日期格式的转换
//根据系统时间获取当前日期 date转stringpublic static String getdate()throws Exception{Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//可以方便地修改日期格式String hehe = dateFormat.format( now ); return hehe;
}//string转datepublic static Date StringToDate(String str) throws Exception {SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");Date date = sdf.parse(str);return date;
}
7.计算当前时间与某个时间点的距离
DateUtil.formatDateTime2((System.currentTimeMillis() - e.getCreatedAt().getTime())/1000)+"前"
/*** Java将秒换算成 时、分、秒格式** @param s 秒* @return*/public static String formatDateTime2(long s) {long day = (s / (60 * 60 * 24));long hours = (s / (60 * 60));long minutes = (s % (60 * 60)) / 60;long seconds = s % 60;if (day > 0) {return day + "天";}if (hours > 0) {return hours + "小时";}if (minutes > 0) {return minutes + "分钟";}if (seconds > 0) {return seconds + "秒";}return "";}
8.二维码生成
@Overridepublic Object generateCode(SmlLnvitationParam param) {try {//通过appId和秘钥获取tokenString accessToken = getAccessToken();String scene = "id=" + param.getId();//调用微信接口生成二维码URL url = new URL("=" + accessToken);HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();// 提交模式httpURLConnection.setRequestMethod("POST");httpURLConnection.setDoOutput(true);httpURLConnection.setDoInput(true);// 获取URLConnection对象对应的输出流PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());// 发送请求参数JSONObject paramJson = new JSONObject();//这就是你二维码里携带的参数 String型 名称不可变paramJson.put("scene", scene);//注意该接口传入的是page而不是path 扫描之后跳转的路径paramJson.put("page", param.getPath());//这是设置扫描二维码的宽度,单位 px,最小 280px,最大 1280px
// paramJson.put("width", 200);//是否需要透明底色,为 true 时,生成透明底色的小程序 默认false
// paramJson.put("is_hyaline", true);//自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
// paramJson.put("auto_color", true);//要打开的小程序版本 正式版为 release,体验版为 trial,开发版为 developparamJson.put("env_version", versions);//检查 page 是否存在 默认为ture检查page false不检查pageparamJson.put("check_path", false);printWriter.write(paramJson.toString());// flush输出流的缓冲printWriter.flush();//开始获取数据ByteArrayOutputStream baos = new ByteArrayOutputStream();InputStream inputStream = httpURLConnection.getInputStream();byte[] buffer = new byte[1024];int num = inputStream.read(buffer);while (num != -1) {baos.write(buffer, 0, num);num = inputStream.read(buffer);}baos.flush();byte[] bytes = baos.toByteArray();String base64EndByte = Base64Util.encode(bytes);base64EndByte = "data:image/png;base64," + base64EndByte;//byte转multipartFile
// MultipartFile multipartFile = fileToMultifile(bytes, "邀请码.png");//上传图片 获取url
// Result<Map<String, String>> fileUploadResourceDTOResult = fileService.upload(multipartFile, 1, true, null,
// "11.png", ScidContext.getScid());
// Map<String, String> data = fileUploadResourceDTOResult.getData();
// checkUploadResult(data);printWriter.close();inputStream.close();baos.close();Map<String,String> map = new HashMap<>(2);
// map.put("url",data.get("url"));map.put("date",base64EndByte);//将返回的二维码流数据上传到oss 生成图片链接String filename = UploadUtil.uploadOne(inputStream, "qrcode.jpeg", bucketName, firstKey);String codeUrl = "https://" + bucketName + "." + UploadUtil.endpoint.substring(UploadUtil.endpoint.indexOf("://") + 3) + "/" + firstKey + filename;return codeurl;} catch (Exception e) {e.printStackTrace();throw new ScException("二维码生成失败");}}
获取token
private String getAccessToken() throws IOException {String requestUrl ="=client_credential&appid=" + appId + "&secret" +"=" + appKey;URL url = new URL(requestUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");// 设置通用的请求属性connection.setRequestProperty("Content-Type", "application/json");connection.setRequestProperty("Connection", "Keep-Alive");connection.setUseCaches(false);connection.setDoOutput(true);connection.setDoInput(true);// 得到请求的输出流对象DataOutputStream out = new DataOutputStream(connection.getOutputStream());out.writeBytes("");out.flush();out.close();// 建立实际的连接connection.connect();// 定义 BufferedReader输入流来读取URL的响应BufferedReader in;if (requestUrl.contains("nlp")) {in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));} else {in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));}StringBuilder result = new StringBuilder();String getLine;while ((getLine = in.readLine()) != null) {result.append(getLine);}in.close();JSONObject jsonObject = JSONObject.parseObject(result.toString());String accessToken = jsonObject.getString("access_token");return accessToken;}
9.微信小程序消息推送
创建发送模板
/*** 微信小程序通知发送** @param userId* @param time* @param address* @param typeName*/private void WechatSend(String userId, String time, String address, String typeName, String recordId) {//构建要发送的消息内容 一个TemplateField代表一个列List<TemplateField> list = new ArrayList<>();TemplateField templateField1 = new TemplateField();templateField1.setName("thing1");templateField1.setValue("xxxx");list.add(templateField1);TemplateField templateField2 = new TemplateField();templateField2.setName("character_string2");templateField2.setValue(time);list.add(templateField2);TemplateField templateField3 = new TemplateField();templateField3.setName("thing3");templateField3.setValue(address);list.add(templateField3);TemplateField templateField4 = new TemplateField();templateField4.setName("thing4");templateField4.setValue("请前往签到或取消");list.add(templateField4);TemplateField templateField5 = new TemplateField();templateField5.setName("thing5");templateField5.setValue(typeName);list.add(templateField5);WxMsgDTO wxMsgDTO = new WxMsgDTO();wxMsgDTO.setUserId(userId);wxMsgDTO.setTemplateId(sendTemplateId);wxMsgDTO.setLink(pages+recordId);wxMsgDTO.setFields(list);iWechatService.Send(wxMsgDTO);}
发送
@Overridepublic Result Send(WxMsg bean) {//发送的执行器Messages messages = wechatAccountUtil.getWechat(bean.getTargetId()).msg();
//发送的用户WxUserinfo wxUserinfo = wxUserinfoRepository.findFirstByUidAndTypeAndDeletedAtIsNull(bean.getUserId(),2);Long messageLong = messages.subscribeSendTemplate(wxUserinfo.getOpenid(), bean.getTemplateId(), bean.getLink(), bean.getFields(), null);return success(messageLong);}
public Long subscribeSendTemplate(String accessToken, String openId, String templateId, String link, List<TemplateField> fields, MiniProgram miniProgram, String requestUrl) {checkNotNullAndEmpty(accessToken, "accessToken");checkNotNullAndEmpty(openId, "openId");checkNotNullAndEmpty(templateId, "templateId");String url = requestUrl + accessToken;Map<String, Object> params = buildSubscribeParams(openId, templateId, link, fields, miniProgram);Map<String, Object> resp = doPost(url, params);Object msgId = resp.get("msgid");return msgId instanceof Long ? (Long) msgId : ((Integer) msgId).longValue();}
构建参数
private Map<String, Object> buildSubscribeParams(String openId, String templateId, String link, List<TemplateField> fields, MiniProgram miniProgram) {Map<String, Object> params = Maps.newHashMapWithExpectedSize(4);params.put("touser", openId);params.put("template_id", templateId);if (!Strings.isNullOrEmpty(link)) {params.put("page", link);}if (!ObjectUtils.isEmpty(miniProgram)) {params.put("miniprogram", miniProgram);}if (fields != null && !fields.isEmpty()) {Map<String, Map<String, String>> data = Maps.newHashMapWithExpectedSize(fields.size());Map<String, String> dataItem;for (TemplateField field : fields) {dataItem = Maps.newHashMapWithExpectedSize(2);dataItem.put("value", field.getValue());dataItem.put("color", field.getColor());data.put(field.getName(), dataItem);}params.put("data", data);}return params;}
10.AOP+注解实现日志入参出参打印
思路:
一个注解类, 一个切面类。使用环绕通知,将入参出参打印出来,可以根据实际情况,有些接口只需要打印即可,有些需要打印并保存到数据库。
注解类GmLog
/*** 自定义日志注解* 1.运行时 使用使用注解* 2.注解作用于方法上* 3.注解是否将包含在 JavaDoc 中*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD };)
@Documented
public @interface GmLog {// 打印日志描述信息String value() default "";// TODO 是否保存到数据库boolean isSave() default false;
};
切面类LogAspect
里面有两种方式,一个是拦截添加注解的方法(适合新建项目,写接口的时候加上注解),一个是指定的包名下面所有的接口(适合现有项目,不必要改变其余代码)
/*** 用于记录注解上接口的入参出参,统一规范。*/
@Aspect
@Component
@Slf4j
public class LogAspect {/*** 方法一: 不需要自定义注解, 直接拦截所有controller的请求。全部打印* 定义切入点表达式* 第一个*号:表示返回类型, *号表示所有的类型。* 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包.* 第二个*号:表示类名,*号表示所有的类。* *(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数*/@Pointcut("execution(public * top.gmaya.gmayaserviceadminimpl.system.controller..*.*(..))")public void privilege() {};/*** 方法二:拦截该注解标识的方法*/@Pointcut("@annotation(top.gmaya.gmayaserviceadminimpl.system.annotation.GmLog)")public void logPointCut() {};/*** 环绕通知* @param pjd* @return* @throws Throwable*/// @Around("privilege()") // 第一种方式@Around("logPointCut()") // 第二种方式public Object arount(ProceedingJoinPoint pjd) throws Throwable {long startTime = System.currentTimeMillis();// 类名String className = pjd.getTarget().getClass().getName();// 获取执行的方法名称String methodName = pjd.getSignature().getName();// 1. 如果是使用的第二种方式,则判断该方法是否使用了改注解// 2. 如果是使用的第一种方式,直接注释即可。GmLog gmLog = this.getAnnotationLog(pjd);if (gmLog != null) {String value = gmLog.value();log.info("{};.{};()【{};】:===================", className, methodName, value);};Object[] args = pjd.getArgs();try {String params = JSON.toJSONString(args[0]);//打印请求参数参数log.info("{};.{};()【方法请求参数为】:{};", className, methodName, params);}; catch (Exception e) {log.info("{};.{};()【方法请求参数打印失败】:{};", className, methodName, e);};// 执行目标方法Object result = pjd.proceed();// 打印返回结果try {String s = JSON.toJSONString(result);log.info("{};.{};()【方法返回结果为】:{};", className, methodName, s);}; catch (Exception e) {log.info("{};.{};()【方法返回结果打印失败】:{};", className, methodName, e);};// 获取执行完的时间long time = System.currentTimeMillis() - startTime;log.info("{};.{};()【方法执行时长为】:{};{};", className, methodName, time, " ms");// 如果使用第一种方式,把这里注释掉// TODO 这里可以考虑新加一个异步方法,保存信息到数据库,入参,出参,请求人,请求时间,ip信息等,如果有异常,还有异常信息。if (gmLog != null) {boolean save = gmLog.isSave();if (save) {String val = gmLog.value();// 调用异步保存数据库方法int i = this.saveLog(pjd, time, val);if (i > 0) {// 判断插入条数,大于0,保存成功。log.info("{};.{};()【{};】:===================", className, methodName, "保存数据库成功!");};};};return result;};/*** 是否存在注解,如果存在就获取* @param joinPoint* @return*/private GmLog getAnnotationLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return method.getAnnotation(GmLog.class);};return null;};/*** 保存到数据库* @param joinPoint* @param time 方法执行时间 单位ms* @param val 方法请求描述* @return*/private int saveLog(JoinPoint joinPoint, long time, String val) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();JSONObject jsonObject = new JSONObject();// ip地址String hostAddress = "";try {hostAddress = InetAddress.getLocalHost().getHostAddress();}; catch (Exception e) {log.error("获取ip失败");};// redis.getUserId(); 结合实际情况 获取当前登录人信息// 类名String className = joinPoint.getTarget().getClass().getName();// 获取执行的方法名称String methodName = joinPoint.getSignature().getName();String url = request.getRequestURL().toString();String method = request.getMethod();jsonObject.put("ip", hostAddress);jsonObject.put("className", className);jsonObject.put("methodName", methodName);jsonObject.put("url", url);// 执行时间jsonObject.put("time", time);jsonObject.put("createTime", new Date());jsonObject.put("createUser", "GMaya");// 操作描述jsonObject.put("operation", val);jsonObject.put("method", method);String s = jsonObject.toJSONString();// 调用日志service的add方法即可!log.info(s);return 1;};};
controller层接口展示:
//只需要添加注解即可,以及是否保存到数据库,默认不保存。@RequestMapping("add")@GmLog(value = "新增登录信息" , isSave = true)public R add(@RequestBody F<UserEntity> f) {// 登录用户信息UserEntity user = this.getUser(f.getToken());return R.data(userService.add(f,user));};
11.JSON格式的转换
@Data
public class Person implements Serializable {
private String name; // 姓名
private int salary; // 薪资
private int age; // 年龄
private String sex; //性别
private String area; // 地区
// 构造方法
// 省略了get和set,请自行添加
}
public class JsonTest {public static void main(String[] args) {Person person1 = new Person("张三",100,20,"男","广州");String personJson = JSONObject.toJSONString(person1);System.out.println("将实体类转为json字符串:"+personJson);JSONObject personJsonObject = (JSONObject) JSONObject.toJSON(person1);System.out.println("将实体类转为json对象:"+personJsonObject);Person person = JSONObject.parseObject(personJsonObject.toJSONString(), Person.class);System.out.println("json对象转某个对象:"+person.toString());System.out.println("上面方法会出现一个问题,某些值会丢失。替代方法,先转为Map,然后直接通过get取值");Map<String,Person> map = JSONObject.parseObject(personJsonObject.toJSONString(), Map.class);Set<String> strings=map.keySet();Iterator<String> iterator = strings.iterator();while (iterator.hasNext()){System.out.println(map.get(iterator.next()));}System.out.println("===================");String name = (String) personJsonObject.get("name");System.out.println("json对象的属性值:"+name);List<Person> personList = new ArrayList<>();for (int i = 0; i < 5; i++) {Person p = new Person("张三",100,20+i,"男","广州");personList.add(p);}JSONArray personJsonArray = JSONObject.parseArray(JSONObject.toJSONString(personList));System.out.println("list转JSAONArray:"+personJsonArray);Map map1 = new HashMap();map1.put("one",person);map1.put("two",person1);JSONObject mapJsonObject = (JSONObject) JSONObject.toJSON(map1);System.out.println("map<string,object>转Json:"+mapJsonObject);String strJson = personJsonObject.toString();System.out.println("将JSONObject对象转为json字符串:"+strJson);}
}
12.通过地址获取经纬度(高德API)
/*** 根据地址信息获取经纬度,(高德api)*/public static GisPoiDTO addressResolution (String address) {if (StringUtils.isBlank(address)) {throw new Exception("获取定位失败");}GisPoiDTO dto = new GisPoiDTO();String url = "";//构造接口需要的形参String param = "key=" + "4safgsfds333434ad34vf222s354l34l5md" +//活动id"&output=" + "JSON" +"&address=" + address;String result = HttpClientUtil.sendGet(url, param);JSONObject jsonObject = JSONObject.parseObject(result);if ("1".equals(jsonObject.get("status"))) {JSONArray jsonArray = jsonObject.getJSONArray("geocodes");if (!ObjectUtils.isEmpty(jsonArray)) {jsonObject = (JSONObject) jsonArray.get(0);String location = (String) jsonObject.get("location");String[] str = location.split(",");dto.setLng(str[0]);dto.setLat(str[1]);}} else {throw new ScException(RespCode.LOCATION_ERROR);}return dto;}
public class GisPoiDTO implements Serializable {
//===========================数据库字段================================/*** 区域块/线路*/private String id;/*** 纬度*/private String lat;/*** 经度*/private String lng;/*** 地址*/private String addr;/*** 备注*/private String memo;/*** 创建时间*/private Date createdAt;/*** 删除时间*/private Date deletedAt;/*** 修改时间*/private Date updatedAt;/*** 有效时间*/private Date validTime;/*** 数据添加者*/private String author;
//===========================表关联====================================//===========================自定义字段================================/*** 地图类型:百度 google 84坐标*/private String mapType;/*** 地区*/private String district;public GisPoiDTO(String lat, String lng, String addr, String mapType) {this.lat = lat;this.lng = lng;this.addr = addr;this.mapType = mapType;}
}
杂七杂八~~
文章目录
- 1.根据经纬度判断距离
- 2.判断某一时间是否在一个时间区间内
- 3.计算日期为星期几
- 4.判断今天是否超过某个日期
- 5.计算两个日期的天数间隔
- 6.日期格式的转换
- 7.计算当前时间与某个时间点的距离
- 8.二维码生成
- 9.微信小程序消息推送
- 10.AOP+注解实现日志入参出参打印
- 11.JSON格式的转换
- 12.通过地址获取经纬度(高德API)
1.根据经纬度判断距离
/*** 计算距离* @param lng 经度* @param lat 纬度* @return*/private double meter(BigDecimal lng1, BigDecimal lat1, BigDecimal lng, BigDecimal lat){double radiansAX = Math.toRadians(lng.doubleValue()); // 数据库经弧度double radiansAY = Math.toRadians(lat.doubleValue()); // 数据库纬弧度double radiansBX = Math.toRadians(lng1.doubleValue()); // 传入经弧度double radiansBY = Math.toRadians(lat1.doubleValue()); // 传入纬弧度double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX)+ Math.sin(radiansAY) * Math.sin(radiansBY);double acos = Math.acos(cos); // 反余弦值return (6371000 * acos);}
SQL函数
2.判断某一时间是否在一个时间区间内
/**** @param sourceTime* 时间区间,半闭合,如[10:00-20:00)* @param curTime* 需要判断的时间 如10:00* @return* @throws IllegalArgumentException*/public static boolean isInTime(String sourceTime, String curTime) {if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);}if (curTime == null || !curTime.contains(":")) {throw new IllegalArgumentException("Illegal Argument arg:" + curTime);}String[] args = sourceTime.split("-");SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");try {long now = sdf.parse(curTime).getTime();long start = sdf.parse(args[0]).getTime();long end = sdf.parse(args[1]).getTime();if (args[1].equals("00:00")) {args[1] = "24:00";}if (end < start) {if (now >= end && now < start) {return false;} else {return true;}}else {if (now >= start && now < end) {return true;} else {return false;}}} catch (ParseException e) {e.printStackTrace();throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);}}
3.计算日期为星期几
public static Integer getWeek(String date) {String[] split = date.split("-");int year = Integer.parseInt(split[0]);int month = Integer.parseInt(split[1]);int day = Integer.parseInt(split[2]);boolean leap=year%400==0||year%100!=0&&year%4==0; //判断当年是否为闰年int total=year-1980+(year-1980+3)/4;//前几年的天数累积量for(int i=month-1;i>0;i--){switch(i){case 1:case 3:case 5:case 7:case 8:case 10:total+=31;break;case 4:case 6:case 9:case 11:total+=30;break;case 2:total+=leap?29:28;}}total+=day;int week=1;week=(week+total)%7;return week;}
4.判断今天是否超过某个日期
public static boolean afterDate(Date date){String format = cn.hutool.core.date.DateUtil.format(date, "yyyy-MM-dd");//把String转为LocalDateLocalDate localTime=LocalDate.parse(format,DateTimeFormatter.ofPattern("yyyy-MM-dd"));//判断当前日期是否大于指定日期return LocalDate.now().isAfter(localTime);}
5.计算两个日期的天数间隔
public static Long dayGap(Date start,Date end) throws ParseException {DateFormat df = new SimpleDateFormat("yyyy-MM-dd");//Date start = df.parse(df.format(new Date()));Long startTime = start.getTime();Long endTime = end.getTime();Long num=endTime-startTime;// System.out.println("相差天数为:"+num/24/60/60/1000);return num/24/60/60/1000;}
6.日期格式的转换
//根据系统时间获取当前日期 date转stringpublic static String getdate()throws Exception{Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//可以方便地修改日期格式String hehe = dateFormat.format( now ); return hehe;
}//string转datepublic static Date StringToDate(String str) throws Exception {SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");Date date = sdf.parse(str);return date;
}
7.计算当前时间与某个时间点的距离
DateUtil.formatDateTime2((System.currentTimeMillis() - e.getCreatedAt().getTime())/1000)+"前"
/*** Java将秒换算成 时、分、秒格式** @param s 秒* @return*/public static String formatDateTime2(long s) {long day = (s / (60 * 60 * 24));long hours = (s / (60 * 60));long minutes = (s % (60 * 60)) / 60;long seconds = s % 60;if (day > 0) {return day + "天";}if (hours > 0) {return hours + "小时";}if (minutes > 0) {return minutes + "分钟";}if (seconds > 0) {return seconds + "秒";}return "";}
8.二维码生成
@Overridepublic Object generateCode(SmlLnvitationParam param) {try {//通过appId和秘钥获取tokenString accessToken = getAccessToken();String scene = "id=" + param.getId();//调用微信接口生成二维码URL url = new URL("=" + accessToken);HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();// 提交模式httpURLConnection.setRequestMethod("POST");httpURLConnection.setDoOutput(true);httpURLConnection.setDoInput(true);// 获取URLConnection对象对应的输出流PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());// 发送请求参数JSONObject paramJson = new JSONObject();//这就是你二维码里携带的参数 String型 名称不可变paramJson.put("scene", scene);//注意该接口传入的是page而不是path 扫描之后跳转的路径paramJson.put("page", param.getPath());//这是设置扫描二维码的宽度,单位 px,最小 280px,最大 1280px
// paramJson.put("width", 200);//是否需要透明底色,为 true 时,生成透明底色的小程序 默认false
// paramJson.put("is_hyaline", true);//自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
// paramJson.put("auto_color", true);//要打开的小程序版本 正式版为 release,体验版为 trial,开发版为 developparamJson.put("env_version", versions);//检查 page 是否存在 默认为ture检查page false不检查pageparamJson.put("check_path", false);printWriter.write(paramJson.toString());// flush输出流的缓冲printWriter.flush();//开始获取数据ByteArrayOutputStream baos = new ByteArrayOutputStream();InputStream inputStream = httpURLConnection.getInputStream();byte[] buffer = new byte[1024];int num = inputStream.read(buffer);while (num != -1) {baos.write(buffer, 0, num);num = inputStream.read(buffer);}baos.flush();byte[] bytes = baos.toByteArray();String base64EndByte = Base64Util.encode(bytes);base64EndByte = "data:image/png;base64," + base64EndByte;//byte转multipartFile
// MultipartFile multipartFile = fileToMultifile(bytes, "邀请码.png");//上传图片 获取url
// Result<Map<String, String>> fileUploadResourceDTOResult = fileService.upload(multipartFile, 1, true, null,
// "11.png", ScidContext.getScid());
// Map<String, String> data = fileUploadResourceDTOResult.getData();
// checkUploadResult(data);printWriter.close();inputStream.close();baos.close();Map<String,String> map = new HashMap<>(2);
// map.put("url",data.get("url"));map.put("date",base64EndByte);//将返回的二维码流数据上传到oss 生成图片链接String filename = UploadUtil.uploadOne(inputStream, "qrcode.jpeg", bucketName, firstKey);String codeUrl = "https://" + bucketName + "." + UploadUtil.endpoint.substring(UploadUtil.endpoint.indexOf("://") + 3) + "/" + firstKey + filename;return codeurl;} catch (Exception e) {e.printStackTrace();throw new ScException("二维码生成失败");}}
获取token
private String getAccessToken() throws IOException {String requestUrl ="=client_credential&appid=" + appId + "&secret" +"=" + appKey;URL url = new URL(requestUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");// 设置通用的请求属性connection.setRequestProperty("Content-Type", "application/json");connection.setRequestProperty("Connection", "Keep-Alive");connection.setUseCaches(false);connection.setDoOutput(true);connection.setDoInput(true);// 得到请求的输出流对象DataOutputStream out = new DataOutputStream(connection.getOutputStream());out.writeBytes("");out.flush();out.close();// 建立实际的连接connection.connect();// 定义 BufferedReader输入流来读取URL的响应BufferedReader in;if (requestUrl.contains("nlp")) {in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));} else {in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));}StringBuilder result = new StringBuilder();String getLine;while ((getLine = in.readLine()) != null) {result.append(getLine);}in.close();JSONObject jsonObject = JSONObject.parseObject(result.toString());String accessToken = jsonObject.getString("access_token");return accessToken;}
9.微信小程序消息推送
创建发送模板
/*** 微信小程序通知发送** @param userId* @param time* @param address* @param typeName*/private void WechatSend(String userId, String time, String address, String typeName, String recordId) {//构建要发送的消息内容 一个TemplateField代表一个列List<TemplateField> list = new ArrayList<>();TemplateField templateField1 = new TemplateField();templateField1.setName("thing1");templateField1.setValue("xxxx");list.add(templateField1);TemplateField templateField2 = new TemplateField();templateField2.setName("character_string2");templateField2.setValue(time);list.add(templateField2);TemplateField templateField3 = new TemplateField();templateField3.setName("thing3");templateField3.setValue(address);list.add(templateField3);TemplateField templateField4 = new TemplateField();templateField4.setName("thing4");templateField4.setValue("请前往签到或取消");list.add(templateField4);TemplateField templateField5 = new TemplateField();templateField5.setName("thing5");templateField5.setValue(typeName);list.add(templateField5);WxMsgDTO wxMsgDTO = new WxMsgDTO();wxMsgDTO.setUserId(userId);wxMsgDTO.setTemplateId(sendTemplateId);wxMsgDTO.setLink(pages+recordId);wxMsgDTO.setFields(list);iWechatService.Send(wxMsgDTO);}
发送
@Overridepublic Result Send(WxMsg bean) {//发送的执行器Messages messages = wechatAccountUtil.getWechat(bean.getTargetId()).msg();
//发送的用户WxUserinfo wxUserinfo = wxUserinfoRepository.findFirstByUidAndTypeAndDeletedAtIsNull(bean.getUserId(),2);Long messageLong = messages.subscribeSendTemplate(wxUserinfo.getOpenid(), bean.getTemplateId(), bean.getLink(), bean.getFields(), null);return success(messageLong);}
public Long subscribeSendTemplate(String accessToken, String openId, String templateId, String link, List<TemplateField> fields, MiniProgram miniProgram, String requestUrl) {checkNotNullAndEmpty(accessToken, "accessToken");checkNotNullAndEmpty(openId, "openId");checkNotNullAndEmpty(templateId, "templateId");String url = requestUrl + accessToken;Map<String, Object> params = buildSubscribeParams(openId, templateId, link, fields, miniProgram);Map<String, Object> resp = doPost(url, params);Object msgId = resp.get("msgid");return msgId instanceof Long ? (Long) msgId : ((Integer) msgId).longValue();}
构建参数
private Map<String, Object> buildSubscribeParams(String openId, String templateId, String link, List<TemplateField> fields, MiniProgram miniProgram) {Map<String, Object> params = Maps.newHashMapWithExpectedSize(4);params.put("touser", openId);params.put("template_id", templateId);if (!Strings.isNullOrEmpty(link)) {params.put("page", link);}if (!ObjectUtils.isEmpty(miniProgram)) {params.put("miniprogram", miniProgram);}if (fields != null && !fields.isEmpty()) {Map<String, Map<String, String>> data = Maps.newHashMapWithExpectedSize(fields.size());Map<String, String> dataItem;for (TemplateField field : fields) {dataItem = Maps.newHashMapWithExpectedSize(2);dataItem.put("value", field.getValue());dataItem.put("color", field.getColor());data.put(field.getName(), dataItem);}params.put("data", data);}return params;}
10.AOP+注解实现日志入参出参打印
思路:
一个注解类, 一个切面类。使用环绕通知,将入参出参打印出来,可以根据实际情况,有些接口只需要打印即可,有些需要打印并保存到数据库。
注解类GmLog
/*** 自定义日志注解* 1.运行时 使用使用注解* 2.注解作用于方法上* 3.注解是否将包含在 JavaDoc 中*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD };)
@Documented
public @interface GmLog {// 打印日志描述信息String value() default "";// TODO 是否保存到数据库boolean isSave() default false;
};
切面类LogAspect
里面有两种方式,一个是拦截添加注解的方法(适合新建项目,写接口的时候加上注解),一个是指定的包名下面所有的接口(适合现有项目,不必要改变其余代码)
/*** 用于记录注解上接口的入参出参,统一规范。*/
@Aspect
@Component
@Slf4j
public class LogAspect {/*** 方法一: 不需要自定义注解, 直接拦截所有controller的请求。全部打印* 定义切入点表达式* 第一个*号:表示返回类型, *号表示所有的类型。* 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包.* 第二个*号:表示类名,*号表示所有的类。* *(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数*/@Pointcut("execution(public * top.gmaya.gmayaserviceadminimpl.system.controller..*.*(..))")public void privilege() {};/*** 方法二:拦截该注解标识的方法*/@Pointcut("@annotation(top.gmaya.gmayaserviceadminimpl.system.annotation.GmLog)")public void logPointCut() {};/*** 环绕通知* @param pjd* @return* @throws Throwable*/// @Around("privilege()") // 第一种方式@Around("logPointCut()") // 第二种方式public Object arount(ProceedingJoinPoint pjd) throws Throwable {long startTime = System.currentTimeMillis();// 类名String className = pjd.getTarget().getClass().getName();// 获取执行的方法名称String methodName = pjd.getSignature().getName();// 1. 如果是使用的第二种方式,则判断该方法是否使用了改注解// 2. 如果是使用的第一种方式,直接注释即可。GmLog gmLog = this.getAnnotationLog(pjd);if (gmLog != null) {String value = gmLog.value();log.info("{};.{};()【{};】:===================", className, methodName, value);};Object[] args = pjd.getArgs();try {String params = JSON.toJSONString(args[0]);//打印请求参数参数log.info("{};.{};()【方法请求参数为】:{};", className, methodName, params);}; catch (Exception e) {log.info("{};.{};()【方法请求参数打印失败】:{};", className, methodName, e);};// 执行目标方法Object result = pjd.proceed();// 打印返回结果try {String s = JSON.toJSONString(result);log.info("{};.{};()【方法返回结果为】:{};", className, methodName, s);}; catch (Exception e) {log.info("{};.{};()【方法返回结果打印失败】:{};", className, methodName, e);};// 获取执行完的时间long time = System.currentTimeMillis() - startTime;log.info("{};.{};()【方法执行时长为】:{};{};", className, methodName, time, " ms");// 如果使用第一种方式,把这里注释掉// TODO 这里可以考虑新加一个异步方法,保存信息到数据库,入参,出参,请求人,请求时间,ip信息等,如果有异常,还有异常信息。if (gmLog != null) {boolean save = gmLog.isSave();if (save) {String val = gmLog.value();// 调用异步保存数据库方法int i = this.saveLog(pjd, time, val);if (i > 0) {// 判断插入条数,大于0,保存成功。log.info("{};.{};()【{};】:===================", className, methodName, "保存数据库成功!");};};};return result;};/*** 是否存在注解,如果存在就获取* @param joinPoint* @return*/private GmLog getAnnotationLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return method.getAnnotation(GmLog.class);};return null;};/*** 保存到数据库* @param joinPoint* @param time 方法执行时间 单位ms* @param val 方法请求描述* @return*/private int saveLog(JoinPoint joinPoint, long time, String val) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();JSONObject jsonObject = new JSONObject();// ip地址String hostAddress = "";try {hostAddress = InetAddress.getLocalHost().getHostAddress();}; catch (Exception e) {log.error("获取ip失败");};// redis.getUserId(); 结合实际情况 获取当前登录人信息// 类名String className = joinPoint.getTarget().getClass().getName();// 获取执行的方法名称String methodName = joinPoint.getSignature().getName();String url = request.getRequestURL().toString();String method = request.getMethod();jsonObject.put("ip", hostAddress);jsonObject.put("className", className);jsonObject.put("methodName", methodName);jsonObject.put("url", url);// 执行时间jsonObject.put("time", time);jsonObject.put("createTime", new Date());jsonObject.put("createUser", "GMaya");// 操作描述jsonObject.put("operation", val);jsonObject.put("method", method);String s = jsonObject.toJSONString();// 调用日志service的add方法即可!log.info(s);return 1;};};
controller层接口展示:
//只需要添加注解即可,以及是否保存到数据库,默认不保存。@RequestMapping("add")@GmLog(value = "新增登录信息" , isSave = true)public R add(@RequestBody F<UserEntity> f) {// 登录用户信息UserEntity user = this.getUser(f.getToken());return R.data(userService.add(f,user));};
11.JSON格式的转换
@Data
public class Person implements Serializable {
private String name; // 姓名
private int salary; // 薪资
private int age; // 年龄
private String sex; //性别
private String area; // 地区
// 构造方法
// 省略了get和set,请自行添加
}
public class JsonTest {public static void main(String[] args) {Person person1 = new Person("张三",100,20,"男","广州");String personJson = JSONObject.toJSONString(person1);System.out.println("将实体类转为json字符串:"+personJson);JSONObject personJsonObject = (JSONObject) JSONObject.toJSON(person1);System.out.println("将实体类转为json对象:"+personJsonObject);Person person = JSONObject.parseObject(personJsonObject.toJSONString(), Person.class);System.out.println("json对象转某个对象:"+person.toString());System.out.println("上面方法会出现一个问题,某些值会丢失。替代方法,先转为Map,然后直接通过get取值");Map<String,Person> map = JSONObject.parseObject(personJsonObject.toJSONString(), Map.class);Set<String> strings=map.keySet();Iterator<String> iterator = strings.iterator();while (iterator.hasNext()){System.out.println(map.get(iterator.next()));}System.out.println("===================");String name = (String) personJsonObject.get("name");System.out.println("json对象的属性值:"+name);List<Person> personList = new ArrayList<>();for (int i = 0; i < 5; i++) {Person p = new Person("张三",100,20+i,"男","广州");personList.add(p);}JSONArray personJsonArray = JSONObject.parseArray(JSONObject.toJSONString(personList));System.out.println("list转JSAONArray:"+personJsonArray);Map map1 = new HashMap();map1.put("one",person);map1.put("two",person1);JSONObject mapJsonObject = (JSONObject) JSONObject.toJSON(map1);System.out.println("map<string,object>转Json:"+mapJsonObject);String strJson = personJsonObject.toString();System.out.println("将JSONObject对象转为json字符串:"+strJson);}
}
12.通过地址获取经纬度(高德API)
/*** 根据地址信息获取经纬度,(高德api)*/public static GisPoiDTO addressResolution (String address) {if (StringUtils.isBlank(address)) {throw new Exception("获取定位失败");}GisPoiDTO dto = new GisPoiDTO();String url = "";//构造接口需要的形参String param = "key=" + "4safgsfds333434ad34vf222s354l34l5md" +//活动id"&output=" + "JSON" +"&address=" + address;String result = HttpClientUtil.sendGet(url, param);JSONObject jsonObject = JSONObject.parseObject(result);if ("1".equals(jsonObject.get("status"))) {JSONArray jsonArray = jsonObject.getJSONArray("geocodes");if (!ObjectUtils.isEmpty(jsonArray)) {jsonObject = (JSONObject) jsonArray.get(0);String location = (String) jsonObject.get("location");String[] str = location.split(",");dto.setLng(str[0]);dto.setLat(str[1]);}} else {throw new ScException(RespCode.LOCATION_ERROR);}return dto;}
public class GisPoiDTO implements Serializable {
//===========================数据库字段================================/*** 区域块/线路*/private String id;/*** 纬度*/private String lat;/*** 经度*/private String lng;/*** 地址*/private String addr;/*** 备注*/private String memo;/*** 创建时间*/private Date createdAt;/*** 删除时间*/private Date deletedAt;/*** 修改时间*/private Date updatedAt;/*** 有效时间*/private Date validTime;/*** 数据添加者*/private String author;
//===========================表关联====================================//===========================自定义字段================================/*** 地图类型:百度 google 84坐标*/private String mapType;/*** 地区*/private String district;public GisPoiDTO(String lat, String lng, String addr, String mapType) {this.lat = lat;this.lng = lng;this.addr = addr;this.mapType = mapType;}
}