有关软件开发编程知识及学习心得
5月26
Spring Boot项目在多环境下(开发、生产或测试环境)调用不同配置文件方式:

我们知道,一个项目在开发环境、测试环境、生产环境,不同的环境会有不同的配置,比如数据库的配置就不同,那么怎么样才能做到,不用每次换环境的时候,都去修改这些配置呢,下面以我写的一个小案例来作说明。

如下图是我项目的三个配置文件,其中,application.yml是启动服务时,服务器会自动加载的配置文件,而application-dev.yml代表的是开发环境的配置文件,application-prod.yml代表的是生产环境的配置文件,后两个文件在启动服务时,服务器不会自动加载,那么在不同的环境中时怎么调用不同的文件的呢?

点击在新窗口中浏览此图片

方式一、修改配置文件方式

    修改application.yml配置文件,具体内容如下图:

点击在新窗口中浏览此图片

这样,在启动服务时,服务器就会通过application.yml文件去调用application-dev.yml文件。同理,若active: prod,那么服务在启动时,服务器就会调用application-prod.yml文件。也就是说,在开发环境时,只需将application.yml配置文件配置为"dev",而生产环境时,只需将“dev”改为“prod”就可以了。
5月22
通过IDE创建一个springboot项目

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>//这行红色
</plugin>

提示spring-boot-maven-plugin not found。在网上找了有说是通过添加<pluginRepositories>过解决,但是测试之后发觉不起作用。 经过多次尝试,最终spring-boot-maven-plugin指定版本后成功解决。 修改后的pom.xml文件

<plugin>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-maven-plugin</artifactId>  
<version>2.1.3.RELEASE</version>
</plugin>

其实说白了就是没有加上这些Maven插件的版本号,导致Maven无法自动下载插件到本地,基本上提示这个not found的错误都是这个问题引起的。

maven-surefire-plugin、maven-compiler-plugin
这些插件也会出现这种问题,解决方案同上。只要你本地有下这些插件,不管哪个版本,就不会提示这个错误,去掉版本号也无所谓。
5月22
一般情况下我们springboot用Application的main方法启动 ,怎么配置成tomcat启动呢?
首先有几个步骤:

1、<packaging>jar</packaging> 改为=> <packaging>war</packaging>

2、  排除springboot内置和tomcat容器(注:这一步可选)      
      
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 移除嵌入式tomcat插件--> 
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 移除内嵌Tomcat需要重新添加servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
            <scope>provided</scope>
        </dependency>

3、修改启动类,并重写初始化方法
我们平常用main方法启动的方式,都有一个App的启动类,代码如下:

@SpringBootApplication
public class Application {
public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
}
}
3月25

分布式事务解决方案

20:34编程杂谈  From: 本站原创
分布式事务了解吗?你们是如何解决分布式事务问题的?
一般来说,分布式事务的实现主要有以下 5 种方案:

XA 方案
TCC 方案
本地消息表
可靠消息最终一致性方案
最大努力通知方案

两阶段提交方案/XA方案
所谓的 XA 方案,即:两阶段提交,有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。

这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。如果要玩儿,那么基于 Spring + JTA 就可以搞定,自己随便搜个 demo 看看就知道了。

这个方案,我们很少用,一般来说某个系统内部如果出现跨多个库的这么一个操作,是不合规的。我可以给大家介绍一下, 现在微服务,一个大的系统分成几十个甚至几百个服务。一般来说,我们的规定和规范,是要求每个服务只能操作自己对应的一个数据库。

如果你要操作别的服务对应的库,不允许直连别的服务的库,违反微服务架构的规范,你随便交叉胡乱访问,几百个服务的话,全体乱套,这样的一套服务是没法管理的,没法治理的,可能会出现数据被别人改错,自己的库被别人写挂等情况。

如果你要操作别人的服务的库,你必须是通过调用别的服务的接口来实现,绝对不允许交叉访问别人的数据库。


TCC 方案
TCC 的全称是:Try、Confirm、Cancel。

Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行锁定或者预留。
Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。
Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
这种方案说实话几乎很少人使用,我们用的也比较少,但是也有使用的场景。因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大,非常之恶心。

比如说我们,一般来说跟钱相关的,跟钱打交道的,支付、交易相关的场景,我们会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。

而且最好是你的各个业务执行的时间都比较短。

但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码很难维护。


本地消息表
本地消息表其实是国外的 ebay 搞出来的这么一套思想。

这个大概意思是这样的:

A 系统在自己本地一个事务里操作同时,插入一条数据到消息表;
接着 A 系统将这个消息发送到 MQ 中去;
B 系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样保证不会重复处理消息;
B 系统执行成功之后,就会更新自己本地消息表的状态以及 A 系统消息表的状态;
如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到 MQ 中去,让 B 再次处理;
这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止。
这个方案说实话最大的问题就在于严重依赖于数据库的消息表来管理事务啥的,会导致如果是高并发场景咋办呢?咋扩展呢?所以一般确实很少用。
1月7
今天使用RequestBody接受前端传过来的参数,以前接受字符串数组非常成功,这次把形参改成了List,原本以为顺利接受参数并映射成User的list结构,结果竟然在我取user.getId()时报了com.alibaba.fastjson.JSONObject cannot be cast to xxx的错。

后端:
@RequestMapping("/insertUser")
public void insertBlank(@RequestBody List userList) {
     User user = userList.get(0);
     System.out.println(user.getId());
}


我的user对象没有转换成功,还是一个一个JSONObject,但是请观察,JSONArray转换成了ArrayList。

  嗯,配置的映射转换器生效了,结果表明,RequestBody能直接将json对象映射成java对象,但仅限于第一层的对象,至于嵌套的对象,则需要开发者自己去转换。

@RequestMapping("/insertUser")
public void insertUser(@RequestBody List list) {
    List userList = list.stream().map(json -> JSONObject.toJavaObject(json, User.class)).collect(Collectors.toList());
   service.insertUser(userList);
}
12月20
首先从以下几点来介绍:
1.为什么要使用synchronized

在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。

2.实现原理

synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性

3.synchronized的三种应用方式

Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:

普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁
静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁
同步方法块,锁是括号里面的对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
4.synchronized的作用

Synchronized是Java中解决并发问题的一种最常用最简单的方法 ,他可以确保线程互斥的访问同步代码
12月19
在tomcat启动时报invalid LOC header (bad signature)错误,这个问题真是搞死人啊,原来是一个jar的问题,删除让maven重新下载就好了,搞了我半天。

Caused by: java.lang.IllegalArgumentException: java.util.zip.ZipException: invalid LOC header (bad signature)  
    at org.apache.catalina.webresources.AbstractSingleArchiveResourceSet.initInternal(AbstractSingleArchiveResourceSet.java:142)  
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)  
    ... 12 more  
Caused by: java.util.zip.ZipException: invalid LOC header (bad signature)  
    at java.util.zip.ZipFile.read(Native Method)  
    at java.util.zip.ZipFile.access$1400(ZipFile.java:60)  
    at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:734)  
    at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:434)  
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)  
    at sun.misc.IOUtils.readFully(IOUtils.java:65)  
    at java.util.jar.JarFile.getBytes(JarFile.java:425)  
    at java.util.jar.JarFile.getManifestFromReference(JarFile.java:193)  
    at java.util.jar.JarFile.getManifest(JarFile.java:180)  
    at org.apache.catalina.webresources.AbstractSingleArchiveResourceSet.initInternal(AbstractSingleArchiveResourceSet.java:140)  
    ... 13 more  

下面是用于定位哪个jar文件没正常被加载的

点击在新窗口中浏览此图片
10月26
先来认识一下微信屏蔽的原理。按原理逐个攻破,整理如下:微信屏蔽的原理

一、微信系统的两个检测手段:第一是系统的自动检测;第二是微信工作人员的人工检测。

二、 人工的检测很好理解,有用户投诉举报,在多少时间内积累多少次的举报量 ,就有工作人员介入,开始人工检测。—–大站做防护解决。

三、自动检测系统是用户访问域名后跟踪域名内部非法违规的关键字——–跳转代码解决


淘宝客微信域名防封技术,如何防屏蔽?

系统或人工拉黑处理,同时记录域名以及路径——更换域名解决。

具体解决方法:

一、老站和知名站点的域名其实是跳板原理,建站时间久和行业内相对知名的域名最不容易被微信封杀,

当跳转代码注入到上述网站再利用安防等我网址做跳转,指向落地页,被微信封杀的可能性微乎其微;

也有同行用融合软件解决,这个问题我可以和大家单独讨论。


二、微信域名检测接口

微信域名检测接口,推荐使用一家的,快速而且稳定。

三、换域名和屏蔽微信右上角举报按钮把A域名,作为分享域名; 把B域名,作为落地域名(也就是用户访问看到的域名); 只有从A域名跳转到B域名,B域名显示的才是我们想展示给用户的内容,如果直接复制B的网址,打开的只是一个错误页面或者不违规的内容,也就是说如果TA点击右上角举报,举报的和访问的虽然是同一个网址,可是显示的内容却不同。

从而最大限度的防止域名被封杀。通过技术,屏蔽微信右上角的举报按钮,直接让用户无法举报,直接屏蔽了微信的举报功能,效果很不错。微信技术在不断升级更新,以后有机会把防屏蔽机制和经验总结给大家交流。
10月25
为方便大家接入这种第三方电商平台推广也方便自己以后查看参考:

开发配置:java、jdk1.8、idea、springboot、windows

一、拼多多

1、进入拼多多开放平台 http://open.pinduoduo.com/#/index 注册为开发者
点击在新窗口中浏览此图片
10月25
1、通过联盟下载的excel订单,可以看出每一个订单的唯一标识符有两个

    (1). 订单号

    (2). pid推广位

2、订单号在用户那里无法自动获取,区分订单方式

    (1). 让用户提交订单号(体验效果不好)

    (2). 给用户绑定一个pid(推荐)

3、目前联盟可以创建pid,上万个(具体多少没有统计)

    (1). 提前创建好pid 1万个插入数据库(可以借助软件),当用户注册的时候,随机分配一个pid进行绑定

    (2). 然后通过转链API接口,生成当前用户pid的推广链接,当用户购买以后,就会产生对应的pid订单,

    (3). 将联盟订单时时同步倒是数据库(可以借助软件30秒同步一次,1分钟同步一次)

    (4). 根据用户当前pid,查询对应订单

4、用到的技术

    (1). 转链高佣金API(官方API,高级权限)

    (2). 订单同步软件(或者官方API,高级权限)

    https://open.taobao.com/api.htm?docId=33892&docType=2

5:pid创建软件(目前没有API,模拟请求创建)
点击在新窗口中浏览此图片
分页: 1/15 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]