This website requires JavaScript.

聊聊开发中幂等性问题

原文地址:聊聊开发中幂等性问题

幂等 (idempotence) 的概念

幂等的数学概念

幂等是源于一种数学概念。其主要有两个定义

如果在一元运算中,x 为某集合中的任意数,如果满足 f(x) = f(f(x)) ,那么该 f 运算具有幂等性,比如绝对值运算 abs(a) = abs(abs(a)) 就是幂等性函数。

如果在二元运算中,x 为某集合中的任意数,如果满足 f(x,x) = x,前提是 f 运算的两个参数均为 x,那么我们称 f 运算也有幂等性,比如求大值函数 max(x,x) = x 就是幂等性函数。

Read more

Spring Boot+SQL/JPA实战悲观锁和乐观锁

最近在公司的业务上遇到了并发的问题,并且还是很常见的并发问题,算是低级的失误了。由于公司业务相对比较复杂且不适合公开,在此用一个很常见的业务来还原一下场景,同时介绍悲观锁和乐观锁是如何解决这类并发问题的。

公司业务就是最常见的“订单+账户”问题,在解决完公司问题后,转头一想,我的博客项目Fame中也有同样的问题(虽然访问量根本完全不需要考虑并发问题...),那我就拿这个来举例好了。

Read more

使用Docker部署Spring-Boot+Vue博客系统

在今年年初的时候,完成了自己的个Fame博客系统的实现,当时也做了一篇博文Spring-boot+Vue = Fame 写blog的一次小结作为记录和介绍。从完成实现到现在,也断断续续的根据实际的使用情况进行更新。

只不过每次上线部署的时候都觉得有些麻烦,因为我的服务器内存太小,每次即使只更新了前台部分(fame-front)的代码,在执行npm build的时候都还必须把我的后端服务(fame-server)的进程关掉,不然会造成服务器卡死(惨啊)。

而且这个项目是前后端分离的,博客前台页面还为了SEO用了Nuxt框架,假如是第一次部署或者要服务器迁移的话,麻烦的要死啊,部署一次的话要以下步骤

  1. 安装mysql,修改相关配置文件,设置编码时区等,然后重启
  2. 下载安装java,配置java环境
  3. 下载安装maven,配置maven环境
  4. 下载安装nginx,修改配置文件,设计反向代理等
  5. 启动spring-boot项目
  6. 打包vue项目,npm install,npm run build
  7. 启动nuxt项目,npm install,npm run start

如果能够顺利的完成这七个步骤算是幸运儿了,假如中间哪个步骤报错出了问题,可能还要回头查找哪个步骤出了问题,然后又重新部署。

我选择死亡

在这些需求面前,Docker就是解决这些问题的大杀器。无论是其虚拟化技术隔离各个容器使其资源互不影响,还是一致的运行环境,以及docker-compose的一键部署,都完美的解决了上述问题。

Read more

从零开始实现一个简易的Java MVC框架(九)--优化MVC代码

前言

从零开始实现一个简易的Java MVC框架(七)--实现MVC中实现了doodle框架的MVC的功能,不过最后指出代码的逻辑不是很好,在这一章节就将这一部分代码进行优化。

优化的目标是1.去除DispatcherServlet请求分发器中的http逻辑代码;2.将ControllerHandlerResultRender中代码按功能细分出来,使其各司其职。

Read more

从零开始实现一个简易的Java MVC框架(八)--制作Starter

spring-boot的Starter

一个项目总是要有一个启动的地方,当项目部署在tomcat中的时候,经常就会用tomcat的startup.sh(startup.bat)的启动脚本来启动web项目

而在spring-boot的web项目中基本会有类似于这样子的启动代码:

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

这个方法实际上会调用spring-boot的SpringApplication类的一个run方法:

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        // 1.加载环境变量、参数等
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                                                                 applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        // 2.加载Bean(IOC、AOP)等
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments,
                       printedBanner);
        //会调用一个AbstractApplicationContext@refresh()方法,主要就是在这里加载Bean,方法的最后还会启动服务器
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

这段代码还是比较长的,不过实际上主要就做了两个事情:1.加载环境变量、参数等 2.加载Bean(IOC、AOP)等。3.如果获得的ApplicationContextServletWebServerApplicationContext,那么在refresh()之后会启动服务器,默认的就是tomcat服务器。

我觉得spring-boot启动器算是spring-boot中相对来说代码清晰易懂的,同时也非常容易了解到整个spring-boot的流程结构,建议大家能够去看一下。

Read more