> <songxiankun@tincerefood.com>
***
* svn://172.16.12.187/project/V1.0/ZXTF/项目管理
* 用户:songxiankun
* 密码:sxk\@123
***
\==2019-01-15 数据迁移,操作生产预发库笔记==
* ①用rewrite Nginx 全部拦截;挂出维护公告,让用户不能访问进服务器,完全阻断了流量
* ②在无数据库访问的情况下,可以对数据进行冷备份。比如<code>elasticSearch,Redis</code>等;在有数据访问的情况下备份数据的话要出错,只能将服务给停了再备份。
* ③生产发版本的安全性,不完全在界面或者命令行操作。比如可以在界面输入版本号,在Linux上选择要重发的服务
* ④项目发布后,希望内网访问测试,不希望外网能访问。此时要设置Nginx的白名单和黑名单
* eg:
<!---->
(上面第一点)
---------------------------------------------------------------
server {
listen 80;
server_name s-name.com www.s-name.com;
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443 ssl;
server_name www.s-name.com;
ssl_certificate 1_s-name.com_bundle.crt;
ssl_certificate_key 2_s-name.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
上面是通过80端口访问s-name.com的请求,全部,重定向到另一个页面[此处是全部转发到443端口]
otherDemo:
server {
listen 80;
server_name abc.com;
rewrite ^/(.*) http://www.abc.com/$1 permanent;
}
---------------------------------------------------------------
(上面第二点)
---------------------------------------------------------------
allow/deny
语法:allow/deny address |CIDR|unix:|all:
默认值:None
区间:http,server,location,limit_except
允许/禁止 一个ip或者ip段访问
eg:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24; 斜杠表示ip段的意思
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
eg:
#屏蔽单个IP的命令是
deny 192.168.1.1
#封整个段即从123.0.0.1到123.255.255.254的命令
deny 123.0.0.0/8
#封IP段即从123.45.0.1到123.45.255.254的命令
deny 124.45.0.0/16
#封IP段即从123.45.6.1到123.45.6.254的命令是
deny 123.45.6.0/24
也就是说,如果最后的斜杠后的数值:
8:匹配后三位最大值的
16:匹配后两位最大值的
24:匹配后一位最大值的
---------------------------------------------------------------
1. @Repository(不是用的service这一套,是Repository,不是Mybatis)
<!---->
@Query("SELECT COUNT(o) FROM Order o WHERE o.userId=:userId AND o.status=:status AND o.deleteStatus=0")
Integer orderStatistics(@Param("userId") Long userId, @Param("status") OrderStatus status);
1. 流处理,过滤器,匹配相等 (仅能用于集合,不能用于对象来遍历!)
<!---->
List<CartItemRo> list = cartItemRos.stream().filter(x -> STORE.equals(x.getDepotCode())).collect(Collectors.toList());
// for (int i = 0; i < cartItemRos.size(); i++) {
// CartItemRo cartItemRo = cartItemRos.get(i);
// if ("STORE".equals(cartItemRo.getDepotCode())) {
// list.add(cartItemRo);
// }
// }
1. new一个集合的方式:
```
Set<String> codes = Sets.newHashSet();
/** 源码 是通过集合的工具来创建的,与直接 new HashSet()没有区别 **/
public static <E> HashSet<E> newHashSet() {
return new HashSet();
}
```
1. 判断集合中有没有自己需要的值
* <code> codes.contains(STORE)</code>
2. 控制跨域访问
<!---->
@Slf4j
public class AuthFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//TODO 修改为可配置
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//这里填写你允许进行跨域的主机ip
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
//允许的访问方法
httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
//Access-Control-Max-Age 用于 CORS 相关配置的缓存
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
1. 时间格式化
* 第一种
<!---->
groupBuy.setStartDate(new Timestamp(DateUtils.parseDate(String.format("%s %s", groupBuyReqVo.getStartDate(), groupBuyReqVo.getStartTime()), "yyyy-MM-dd HH:mm").getTime()));
groupBuy.setEndDate(new Timestamp(DateUtils.parseDate(String.format("%s %s", groupBuyReqVo.getEndDate(), groupBuyReqVo.getEndTime()), "yyyy-MM-dd HH:mm").getTime()));
groupBuy.setStartTime(new Timestamp(DateUtils.parseDate(groupBuyReqVo.getStartTime(), "HH:mm").getTime()));
groupBuy.setEndTime(new Timestamp(DateUtils.parseDate(groupBuyReqVo.getEndTime(), "HH:mm").getTime()));
* 第二种
<!---->
Timestamp startTime = new Timestamp(DateUtils.parseDate(groupBuyReqVo.getStartTime(), "HH:mm").getTime());
Timestamp startTime = new Timestamp(groupBuyReqVo.getStartTime().getTime() - DateUtils.truncate(groupBuyReqVo.getStartDate(), Calendar.DATE).getTime());
Timestamp endTime = new Timestamp(DateUtils.parseDate(groupBuyReqVo.getEndTime(), "HH:mm").getTime());
Timestamp endTime = new Timestamp(groupBuyReqVo.getEndTime().getTime() - DateUtils.truncate(groupBuyReqVo.getEndDate(), Calendar.DATE).getTime());
Timestamp startDate = new Timestamp(DateUtils.parseDate(String.format("%s %s", groupBuyReqVo.getStartDate(), groupBuyReqVo.getStartTime()), "yyyy-MM-dd HH:mm").getTime());
Timestamp endDate = new Timestamp(DateUtils.parseDate(String.format("%s %s", groupBuyReqVo.getEndDate(), groupBuyReqVo.getEndTime()), "yyyy-MM-dd HH:mm").getTime());
groupBuy.setEndTime(endTime);
groupBuy.setStartTime(startTime);
groupBuy.setStartDate(startDate);
groupBuy.setEndDate(endDate);
1. 对象比较
Objects.equals(order.getUserId()
1. SQL
<!---->
@Query("SELECT COUNT(o) FROM Order o WHERE o.userId=:userId AND o.status=:status AND o.deleteStatus=0")
Integer orderStatistics(@Param("userId") Long userId,@Param("status") OrderStatus status);
1. 时间戳的比较
<!---->
order.getPaymentLastTime().after(new Timestamp(System.currentTimeMillis()));
1. 查询参团对象:根据数据库中的List,并根据List中每条对象中的属性计算出的差值排序
service层:
<!---->
List<GroupBuyActivity> byActiveId = activityRepository.findAllByGroupBuyIdAndStatusIn(activeId, Arrays.asList(GroupBuyActivityStatus.ACTIVITY_RUNNING, GroupBuyActivityStatus.SUCCESS));
AssertUtils.notNull(byActiveId, GroupBuyActivityException.NOT_FOUNT_ACTIVITY);
byActiveId.stream().parallel().forEach(x -> x.setPayAmount(0L));
byActiveId.sort((x, y) -> {
int a = x.getGroupPeoples() - x.getJoinPeoples(), b = y.getGroupPeoples() - y.getJoinPeoples();
if (a == b) {
return 0;
}
return a - b;
});
return byActiveId;
Repository层:
List<GroupBuyActivity> findAllByGroupBuyIdAndStatusIn(Long activityId, List<GroupBuyActivityStatus> statuses);
1. 流式demo
<!---->
reqVo.getItems().stream().map(ProductQuantityPair::getProductCode).collect(Collectors.toSet());
pair.stream().collect(Collectors.toMap(ProductQuantityPair::getProductCode, ProductQuantityPair::getQuantity));
1. <code>ls -lrt | grep rest | tail -1 </code>
【-r 逆序显示内容(包括时间、字母),最新的文件在最下面 -t sort by modification time】
1. 时间截断再拼接(\*\*\*\*)
<!---->
Timestamp finalTime = Timestamp.valueOf(LocalDateTime.of(groupBuyReqVo.getEndDate().toLocalDateTime().toLocalDate(), groupBuyReqVo.getEndTime().toLocalDateTime().toLocalTime()));
用A的日期和B的时间拼装成一个完成的日期时间C
完整版本:
public final Date joinDateAndTime(long date, long time) {
final ZoneId defaultZoneId = ZoneOffset.systemDefault();
LocalDateTime dateTime = LocalDateTime.of(LocalDateTime.ofInstant(Instant.ofEpochMilli(date), defaultZoneId).toLocalDate(), LocalDateTime.ofInstant(Instant.ofEpochMilli(time), defaultZoneId).toLocalTime());
return Date.from(dateTime.atZone(defaultZoneId).toInstant());
}
1. 由于分支名:4.0-Version 与jenkins的特殊字符 “-” 冲突,会导至出现 jenkins的发布bug,请大家切换一下分支,如:4.0\_Version
2. unalias rm 解锁删除命令
3. 分页Demo
<!---->
productListVos.stream().skip((page-1)*pageSzie).limit(pageSzie).collect(Collectors.toList());
1. swagger 坑
swagger中各对象的ApiModel名称不能重复。然会重复名称的类,会显示其中的一个类的字段。
显示混乱。
@Setter
@Getter
@ApiModel("签到活动查询响应对象")
public class SignActivityRespVO
1. 查看属性, 磁盘文件大小什么的 <code>du -sh \* / du -sh aaa.txt</code>
20.倒序并限制条数
collect = allCoupons.stream().sorted((x, y) -> y.getDenomination().compareTo(x.getDenomination())).limit(3).collect(Collectors.toList());
1. 获取一天中最大的时间和最小的时间
// 获得某天最大时间 2017-10-15 23:59:59
public static Date getEndOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());;
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
<!---->
// 获得某天最小时间 2017-10-15 00:00:00
<!---->
public static Date getStartOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
1. 将Array倒序<code>Collections.reverse( List )</code>;
2. BigDecimal除法
* 除法,保留两位小数
<!---->
(new BigDecimal(po.getDenomination()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString()));
* 乘法
<!---->
byProductCode.getFinalPrice().multiply(new BigDecimal(100)).intValue())
<!---->
String s = BigDecimal.valueOf(i.getDiscountValue()).multiply(new BigDecimal(10)).setScale(1, BigDecimal.ROUND_HALF_UP).toString(); // 乘法保留小数;四舍五入
1.
List<Order> list = page.getContent();
list.forEach(this::orderCheck); 额,有空了看看这个集合怎么遍历的,遍历了它干啥
1.
//筛选显示按钮
Set<Boolean> collect = Optional.ofNullable(respVO.getProductListVos()).orElse(new ArrayList<>()).stream()
.map(item -> Boolean.TRUE.equals(item.getContentStatus())).collect(Collectors.toSet());
这又是一个高级的 Lambda 表达式
26.排序并过滤
myStoreCouponsAmount.stream().filter(i -> i.getDenomination() != null).sorted((x, y) -> y.getDenomination().compareTo(x.getDenomination())).limit(6).collect(Collectors.toList());
1. Map获取value : <code>useAbleCoupons.getOrDefault(resp.getCode(), 0));</code> \[ 有 default 表示可以默认]
2. Lambda 分组
<!---->
receiveMap = PkgS.stream().collect(Collectors.toMap(CouponPkgVo::getCode, v -> Boolean.TRUE, (v1, v2) -> Boolean.TRUE));
useAbleCoupons = PkgS.stream().filter(i -> com.biz.primus.model.coupon.enums.CouponStatus.UNUSE == i.getStatus())
.collect(Collectors.groupingBy(CouponPkgVo::getCode))
1. subList list 的截取方法 类似于Lambda的 .skip().limit() ; 只是如果数量少于分页容量涵盖的时候,会抛出空指针
2. 一个日志文件太大,将文件按照大小进行切分; eg:
<!---->
split -b 1000m app.log depot_
* 将 app.log这个文件,拆分成无数个1000M大小的子文件,每个文件的前缀是depot\_ 文件的命名是 aa,ab,ac..ZZZZ
1. 根据关键词来过滤文本; 相当于快速查询关键词
<code>grep -a BJ0010102244 depot\_aj </code>
打印出文本为BJ0010102244相关的行数在depot\_aj这个日志文件中
1. 访问端口
<!---->
[telnet s-name.club 444] 测试该端口是否是通的
1. 高级去重复
* 根据某个字段来判断是否重复!
<!---->
list.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingLong(MicroGroupBuy::getActiveId))), ArrayList::new));
此种方法可能会存在断流等问题;
<!---->
高级去重复:
ArrayList<CouponProductsReqVo> list = new ArrayList<>();
Map map = Maps.newConcurrentMap();
list.stream().filter(s->map.putIfAbsent(s.getCouponCode(),true)== null).collect(Collectors.toList());
1. 排序:
<!---->
根据某个字段
Collections.sort(apply, Comparator.comparing(MicroGroupBuySaveRespVo::getSerialNumber).reversed());
1. 对日志中某个时间段的内容进行截取:
<!---->
sed -n '/16:50:/,/17:00:/p' app-oms.log-20190702-ms5-774M > app-oms.log
将日志 app-oms.log-20190702-ms5-774M 截取 16:50 到 17:00 时间范围内的日志,输出生产新的文件
1. ShardedJedis 模糊查询
<!---->
jedis.getShard(“somekey 可以乱写,好像没得影响”).keys(“some pattern ==> microWeChat:*”);
37 . 查看内存占用最凶的10条进程
ps aux|head -1; ps aux | sort -k4nr | head -10
37.5 FeignClient
* Feign
```
@FeignClient(qualifier = "communityMessageFeignClient", name = "SERVICE-MESSAGE-NEW", fallbackFactory = CommunityMessageFeignClient.FallbackFactory.class)
public interface CommunityMessageFeignClient {
@Slf4j
@Component
class FallbackFactory implements feign.hystrix.FallbackFactory<CommunityMessageFeignClient> {
@Autowired
private DegradedCommunityMessageFeignClient fallbackClient;
@Override
public CommunityMessageFeignClient create(Throwable cause) {
if (cause != null && !cause.getClass().equals(RuntimeException.class)) {
log.error("----->>>>>>>>> service-oms ---->>>>> 调用 service-message-new 异常", cause);
}
return fallbackClient;
}
}
/**
* 发送模板消息
*
* @param microWeChatSendTempReqVo
* @return
*/
@RequestMapping(value = "/soa/message/weChat/tempMessage/sendTempMsg", method = RequestMethod.PATCH)
Boolean sendTemplateMessage(@RequestBody MicroWeChatSendTempReqVo microWeChatSendTempReqVo);
}
```
* Degraded
<!---->
@Slf4j
@Component
public class DegradedCommunityMessageFeignClient implements CommunityMessageFeignClient {
@Override
public Boolean sendTemplateMessage(MicroWeChatSendTempReqVo microWeChatSendTempReqVo) {
log.warn(" service-order 调用 service-message-new 进入熔断!");
return null;
}
}
38 . 多传参数
```
public <T extends Dict> void removeEqual(T dict, String... withoutNames) {
HashSet<String> withoutSet = CollectionUtil.newHashSet(withoutNames);
```
39 . 对集合里面的某个子集合的属性进行过滤判断
```
List<SeparateAccount> posterList = needToPushForPoster.stream().filter(i -> {
List<Boolean> b = Lists.newArrayList();
i.getItems().forEach(j -> {
b.add(AccountAttributionType.DELIVERY.equals(j.getAccountAttributionType()));
});
return b.stream().anyMatch(a -> a);
}
).collect(Collectors.toList());
```
1. 单个对象转为的List的优化方法:
<!---->
Arrays.asList ==> Collections.singletonList
1. 判断集合里面的子项里面的枚举项是否满足前面两个的枚举
```
Lists.newArrayList(SeparateAccountType.PLATFORM_INCOME_TO_REPAYMENT, SeparateAccountType.PLATFORM_COMMISSION_TO_REPAYMENT).contains(item.getAccountType()))
```
1. 创建一个分步的过滤条件:
<!---->
java.util.function.Predicate<CouponPkgPo> predicate = pkg -> {
// 满减券,满足门槛使用
if (CouponUseType.DOORFILL.equals(pkg.getCoupon().getType())) {
return products.stream().filter(x -> pkg.getGoods().contains(-1L) || pkg.getGoods().contains(x.getProductId())).mapToInt(OrderProduct::getTotalAmount).sum() >= pkg.getCoupon().getFloorSill();
}
// 魔法变品券,无门槛
// 魔法变价券,无门槛
// 运费券,无门槛
// 直降券,无门槛
// 礼品券适用于所有商品
return true;
};
useList = useList.stream().filter(predicate).collect(Collectors.toList());
43.JPA的字段备注(数据库字段备注)
```
@Column(length = 64, columnDefinition = "varchar(64) comment 'formId【String】'")
@Column(columnDefinition = "longtext COMMENT '模板内容【longtext】'")
@Column(length = 11, columnDefinition = "int(11) comment '模板类型【这是枚举】'")
@Column(columnDefinition = "datetime comment '推送时间【时间戳】'")
@Column(length = 11, columnDefinition = "bigint(11) comment '用户ID【Long】'")
@Column(length = 11, columnDefinition = "int(11) comment '是否成功【布尔值】'")
@Column(length = 11, columnDefinition = "int(11) comment '拼团价【Integer】'")
@Column(name = "discountValue", columnDefinition = "double(3,2) default '0.00' comment '双精度' ")
@Column(columnDefinition = "DECIMAL(19,7) comment '纬度'")
删除一对一或者一对多的时候产生的外键;【单方映射不会有外键,只有关联关系;另一方再映射回来的时候就会彼此产生外键】
前方:@org.hibernate.annotations.ForeignKey(name = "none")
后方: @JoinColumn(name = "wait_code", referencedColumnName = "wait_code", insertable = false
, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
```
44.合并流,并求和
```
int publishDenominationSum = all.stream().mapToInt(i -> i.getItems().stream().mapToInt(MultiAppletItemsPo::getDenomination).sum()).sum();
```
45.判断为空,或抛出异常
Optional.ofNullable(stringJsonResult).filter(b -> 0 == b.getCode()).orElseThrow(() -> new BizSilentException(CouponExceptionType.COUPON_STATUS_ILLEGAL));
46.map的遍历;并求和
publishDenominationSum = itemsPoMap.values().stream().map(value -> value.getDenomination() * value.getRegisterSum()).mapToInt(amount -> amount).sum()
和
publishDenominationSum = itemsPoMap.values().stream().map(value -> value.getDenomination() * value.getRegisterSum()).mapToInt(amount -> amount).sum()
1. 多个字段同时排序
<!---->
productsByActiveId.sort((o1, o2) -> {
if (o1.getSerialNo().equals(o2.getSerialNo())) {
return (int) (o2.getModifySerialNoTime().getTime() - o1.getModifySerialNoTime().getTime());
} else {
return o2.getSerialNo() - o1.getSerialNo();
}
});
--------------------------------------------------------------------
content.sort((o1, o2) -> {
if (o1.getLoseTime().getTime() == o2.getLoseTime().getTime()) {
return o2.getDenomination() - o1.getDenomination();
} else {
return (int) (o1.getLoseTime().getTime() - o2.getLoseTime().getTime());
}
});
过期时间从小到大,当时间一致的时候,金额从大到小
1. 将一个表的值,更新到另一个表
<!---->
UPDATE tincere_oms.order_oms o,tincere_oms.order_commodity c SET c.create_time = o.create_time , c.update_time = o.update_time WHERE c.batch_code_id=o.id ;
45.枚举序列化
@Getter
@AllArgsConstructor
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum MeetingTypeEnum {
EMERGENCY_EXERCISE(0, "应急演练"),
JK_REGULAR_MEETING(1, "井控例会"),
HSE(2, "HSE会议"),
BQ_REGULAR_MEETING(3, "班前例会"),
;
private final Integer code;
private final String desc;
@JsonCreator
MeetingTypeEnum getEnumByCode(Integer code) {
MeetingTypeEnum[] values = MeetingTypeEnum.values();
for (MeetingTypeEnum value : values) {
if (code.equals(value.getCode())) {
return value;
}
}
return null;
}
}
46.SQL
SELECT
sync_time syncTime,
GROUP_CONCAT( DISTINCT tenant_id ) tenantId,
GROUP_CONCAT( DISTINCT platform_id ) platformId,
count( 0 ) count
FROM
sygc_pz_jkdzxzt
GROUP BY
sync_time;
评论区