jooq实践

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: 用法   sql语句 SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*) FROM AUTHOR JOIN BOOK ON AUTHOR.

用法

  sql语句

SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)
    FROM AUTHOR
    JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID
   WHERE BOOK.LANGUAGE = 'DE'
     AND BOOK.PUBLISHED > DATE '2008-01-01'
GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
  HAVING COUNT(*) > 5
ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
   LIMIT 2
  OFFSET 1

  java代码

dsl.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
      .from(AUTHOR)
      .join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
      .where(BOOK.LANGUAGE.eq("DE"))
      .and(BOOK.PUBLISHED.gt(date("2008-01-01")))
      .groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
      .having(count().gt(5))
      .orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
      .limit(2)
      .offset(1)

 

示例代码

增:
public void addMerchantUrgentIsochrone(ITbMerchantUrgentIsochrone merchantUrgentIsochrone) {
    TbMerchantUrgentIsochroneRecord record = dsl.newRecord(TB_MERCHANT_URGENT_ISOCHRONE, merchantUrgentIsochrone);
    record.store();
    merchantUrgentIsochrone.setId(record.getId());
}
删:
public int deleteRecords() {
    return dsl.delete(TB_MERCHANT_URGENT_ISOCHRONE).where(TB_MERCHANT_URGENT_ISOCHRONE.CREATED_AT.ge(Timestamp.valueOf(LocalDateTime.now().minusDays(1)))).execute();
}
改:
public int update(ITbUserArea userArea) {
    return dsl.update(TB_USER_AREA)
            .set(TB_USER_AREA.GEOHASH, userArea.getGeohash())
            .set(TB_USER_AREA.AREA, userArea.getArea())
            .set(TB_USER_AREA.CITY_ID, userArea.getCityId())
            .set(TB_USER_AREA.ORDER_COUNT, userArea.getOrderCount())
            .where(TB_USER_AREA.ID.eq(userArea.getId()))
            .execute();
}
查:
public List<ITbUserArea> getAreas(String preHash) {
    return dsl.selectFrom(TB_USER_AREA)
            .where(TB_USER_AREA.GEOHASH.like(preHash+"%"))
            .fetchInto(TbUserArea.class);
}

jooq 可以执行sql语句

Result<Record> fetch(String var1) throws DataAccessException;
int execute(String var1) throws DataAccessException;

配置篇

  maven配置

Maven依赖:(版本号可配)
<dependency>
  <groupId>org.jooq</groupId>
  <artifactId>jooq</artifactId>
  <version>3.9.5</version>
</dependency>
<dependency>
  <groupId>org.jooq</groupId>
  <artifactId>jooq-meta</artifactId>
  <version>3.9.5</version>
</dependency>
<dependency>
  <groupId>org.jooq</groupId>
  <artifactId>jooq-codegen</artifactId>
  <version>3.9.5</version>
</dependency>
 
工具生成映射配置:
建立 xxx.xml(名字任意)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
    <jdbc>
        <driver>...</driver>
        <url>...</url>
        <user>...</user>
        <password>...</password>
    </jdbc>
    <generator>
        <!-- 指定代码风格
            - org.jooq.util.ScalaGenerator
            - org.jooq.util.JavaGenerator
         -->
        <name>org.jooq.util.JavaGenerator</name>
 
        <database>
            <!-- 数据库类型 -->
            <name>org.jooq.util.postgres.PostgresDatabase</name>
            <!-- <name>org.jooq.util.mysql.MySQLDatabase</name> -->
            <excludes>
                <!-- 对tb_table1,tb_table2,tb_table3 表不生成代码-->
                tb_table1|tb_table2|tb_table3
            </excludes>
            <includeExcludeColumns>true</includeExcludeColumns>
            <inputSchema>public</inputSchema>
 
            <!-- jooq转换对象类型,如用enum代替int
                目标转换类型应实现org.jooq.Converter或org.jooq.Binding接口
                相应的配置标签为<customType>,<forcedType>
                参考地址: https://www.jooq.org/doc/3.9/manual/code-generation/custom-data-types/
                https://www.jooq.org/doc/3.9/manual/code-generation/custom-data-type-bindings/
             -->
            <customTypes>
                <customType>
                    <name>EffectiveStatus</name>
                    <type>xxx.isochrone.constant.EffectiveStatus</type>
                    <converter>xxx.geo.jooq.converter.EffectiveStatusConverter</converter>
                </customType>
            </customTypes>
            <forcedTypes>
                <!-- 使用converter -->
                <forcedType>
                    <name>EffectiveStatus</name>
                    <expressions>.*\.tb_isochrone_audit_info\.effective_status</expressions>
                    <types>.*</types>
                </forcedType>
                <!-- 使用binding -->
                <forcedType>
                    <userType>xxx.isochrone.pojos.GeographyPolygon</userType>
                    <binding>xxx.geo.jooq.binding.PGgeometryPolygonBinding</binding>
                    <expression>.*\.tb_isochrone.range|.*\.tb_merchant_area_isochrone.range</expression>
                    <types>.*</types>
                </forcedType>
            </forcedTypes>
        </database>
 
        <generate>
            <deprecated>false</deprecated>
            <daos>true</daos>
            <interfaces>true</interfaces>
        </generate>
        <target>
            <!-- 生成的包名,生成的类在此包下 -->
            <packageName>xxx.isochrone.jooq</packageName>
            <!-- 输出的目录 -->
            <directory>src/main/java</directory>
        </target>
    </generator>
</configuration>
 
相应pom.xml里添加对应的配置信息
<profiles>
    <profile>
        <id>db-gen</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.4.0</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <includeProjectDependencies>false</includeProjectDependencies>
                        <includePluginDependencies>true</includePluginDependencies>
                        <mainClass>org.jooq.util.GenerationTool</mainClass>
                        <cleanupDaemonThreads>false</cleanupDaemonThreads>
                        <arguments>
                            <!-- 匹配工具生成映射配置文件 -->
                            <argument>xxx.xml</argument>
                        </arguments>
                    </configuration>
                    <dependencies>
                        <dependency>
                          <groupId>org.jooq</groupId>
                          <artifactId>jooq</artifactId>
                          <version>3.9.5</version>
                        </dependency>
                        <dependency>
                            <groupId>org.jooq</groupId>
                            <artifactId>jooq-codegen</artifactId>
                            <version>3.9.5</version>
                        </dependency>
                        <dependency>
                            <groupId>org.jooq</groupId>
                            <artifactId>jooq-meta</artifactId>
                            <version>3.9.5</version>
                        </dependency>
                        <dependency>
                            <groupId>org.postgresql</groupId>
                            <artifactId>postgresql</artifactId>
                            <version>9.4.1208.jre7</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

执行代码自动生成命令
mvn -P db-gen exec:java

  gradle配置

application.yml

spring:
  jooq:
    #请勿动,当使用了ejdbc的配置后,Spring Boot无法识别正确的Dialect
    sqlDialect: Mysql


jooq模块下的gradle文件
apply plugin: 'io.spring.dependency-management' dependencyManagement { resolutionStrategy { cacheChangingModulesFor 0, 'seconds' } imports { mavenBom 'io.spring.platform:platform-bom:Brussels-SR6' mavenBom 'org.jooq:jooq:3.10.1' } dependencies { dependency 'org.springframework.statemachine:spring-statemachine-core:1.2.6.RELEASE' } } apply plugin: 'nu.studer.jooq' emodule { dependency 'tms-jooq-model' } dependencies { compile 'org.jooq:jooq' jooqRuntime 'mysql:mysql-connector-java' } // Jooq Gradle Plugin 参考文档 https://github.com/etiennestuder/gradle-jooq-plugin jooq { version = '3.10.1' tms(sourceSets.main) { jdbc { driver = 'com.mysql.jdbc.Driver' url = 'jdbc:mysql://localhost:3306/test' user = 'xxx' password = 'xxx' } generator { name = 'org.jooq.util.DefaultGenerator' database { name = 'org.jooq.util.mysql.MySQLDatabase' inputSchema = 'scm_tms' outputSchemaToDefault = true includeExcludeColumns = true //重构,相关字段迁移到tb_docker_deployment_log中 excludes = ".*_bak|.*\\.drc_check_time|.*\\.is_delete|.*\\.updated_at" forcedTypes { forcedType { userType = "xxx.common.model.model.GeoPoint" converter = "xxx.jooq.model.converter.GeoPointConverter" expression = ".*_lnglat" types = ".*" } forcedType { userType = "xxx.base.api.model.UsedType" converter = "xxx.jooq.model.converter.VehicleIsUsedTypeConverter" /*A Java regular expression matching fully-qualified columns. Use the pipe to separate several expressions. ->database.table.column*/ expression = ".*\\.base_vehicle\\.is_used" /*Add a Java regular expression matching data types to be forced to have this type*/ types = ".*" } } } generate { relations = true deprecated = false records = true interfaces = true pojos = true daos = false fluentSetters = true } target { packageName = project.groupPrefix + "." + project.groupName + ".db.model" directory = 'src/main/java' } } } } //不自动执行Jooq的代码生成和清除任务 //数据库更改后,手动进入 jooq模块 //执行 gradle cleanGenerateTmsJooqSchemaSource generateTmsJooqSchemaSource //生成数据库对象在tms-db-model下 project.tasks.getByName('compileJava').dependsOn -= 'generateTmsJooqSchemaSource' project.tasks.getByName('clean').dependsOn -= 'cleanGenerateTmsJooqSchemaSource'

 

jooq Converter示例

import xxx.GeoPoint;
import org.jooq.Converter;

public class GeoPointConverter implements Converter<String, GeoPoint> {
    @Override
    public GeoPoint from(String databaseObject) {
        return new GeoPoint(databaseObject);
    }

    @Override
    public String to(GeoPoint point) {
        return point==null?"":point.gdFormat();
    }

    @Override
    public Class<String> fromType() {
        return String.class;
    }

    @Override
    public Class<GeoPoint> toType() {
        return GeoPoint.class;
    }
}

public class GeoPoint {
    /**
     * 经度值
     */
    private Double longitude;
    /**
     * 纬度值
     */
    private Double latitude;

    public GeoPoint() {
    }

    public GeoPoint(String location) {
        if (!StringUtils.isEmpty(location)) {
            String[] lnglat = location.split(",");
            this.longitude = Double.valueOf(lnglat[0]);
            this.latitude = Double.valueOf(lnglat[1]);
        }
    }

    public Double getLongitude() {
        return longitude;
    }

    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }

    public Double getLatitude() {
        return latitude;
    }

    public void setLatitude(Double latitude) {
        this.latitude = latitude;
    }

    public String gdFormat() {
        if (longitude == null || latitude == null) {
            return "";
        }
        return longitude + "," + latitude;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        GeoPoint geoPoint = (GeoPoint) o;

        if (longitude != null ? !longitude.equals(geoPoint.longitude) : geoPoint.longitude != null) return false;
        return latitude != null ? latitude.equals(geoPoint.latitude) : geoPoint.latitude == null;
    }

    @Override
    public int hashCode() {
        int result = longitude != null ? longitude.hashCode() : 0;
        result = 31 * result + (latitude != null ? latitude.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "GeoPoint{" +
                "longitude=" + longitude +
                ", latitude=" + latitude +
                '}';
    }

}

 

import xxx.scm.tms.common.model.model.WarehouseType;
import org.jooq.Converter;

/**
 * WarehouseTypeConverter
 */
public class WarehouseTypeConverter implements Converter<Byte, WarehouseType> {
    @Override
    public WarehouseType from(Byte databaseObject) {
        return WarehouseType.getTypeByCode(databaseObject);
    }

    @Override
    public Byte to(WarehouseType warehouseType) {
        return warehouseType.getCode();
    }

    @Override
    public Class<Byte> fromType() {
        return Byte.class;
    }

    @Override
    public Class<WarehouseType> toType() {
        return WarehouseType.class;
    }
}

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

public enum WarehouseType {
    NORMAL_TEMPERATURE((byte)1, "常温"),
    COLD_STORAGE((byte)2, "冷藏"),
    FREEZING((byte)3, "冷冻");

    private byte code;
    private String label;

    WarehouseType(byte code, String label) {
        this.code = code;
        this.label = label;
    }

    public byte getCode() {
        return code;
    }

    public String getLabel() {
        return label;
    }

    private static Map<Byte, WarehouseType> map = new HashMap<>();
    static {
        EnumSet.allOf(WarehouseType.class)
                .forEach(e -> map.put(e.getCode(), e));
    }

    public static WarehouseType getTypeByCode(Byte code) {
        return map.get(code);
    }
}

 

高级用法代码示例

public List<BaseWarehouse> searchWarehouses(WarehouseCondition warehouseCondition) {
    SelectConditionStep<?> step = dsl.selectFrom(Tables.BASE_WAREHOUSE).where(DSL.trueCondition());

    StringBuilder likeValue = new StringBuilder();

    if (!Objects.isNull(warehouseCondition.getWarehouseId())) {
        step.and(Tables.BASE_WAREHOUSE.WAREHOUSE_ID.eq(warehouseCondition.getWarehouseId()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getWarehouseName())) {
        likeValue.setLength(0);
        likeValue.append("%").append(warehouseCondition.getWarehouseName()).append("%");
        step.and(Tables.BASE_WAREHOUSE.WAREHOUSE_NAME.likeIgnoreCase(likeValue.toString()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getCompany())) {
        likeValue.setLength(0);
        likeValue.append("%").append(warehouseCondition.getCompany()).append("%");
        step.and(Tables.BASE_WAREHOUSE.COMPANY.likeIgnoreCase(likeValue.toString()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getProvinceName())) {
        step.and(Tables.BASE_WAREHOUSE.PROVINCE_NAME.eq(warehouseCondition.getProvinceName()));
    }

    if (!Objects.isNull(warehouseCondition.getProvinceId())) {
        step.and(Tables.BASE_WAREHOUSE.PROVINCE_ID.eq(warehouseCondition.getProvinceId()));
    }


    if (StringUtils.isNotBlank(warehouseCondition.getCityName())) {
        step.and(Tables.BASE_WAREHOUSE.CITY_NAME.eq(warehouseCondition.getCityName()));
    }

    if (!Objects.isNull(warehouseCondition.getCityId())) {
        step.and(Tables.BASE_WAREHOUSE.CITY_ID.eq(warehouseCondition.getCityId()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getDistrictName())) {
        step.and(Tables.BASE_WAREHOUSE.DISTRICT_NAME.eq(warehouseCondition.getDistrictName()));
    }

    if (!Objects.isNull(warehouseCondition.getDistrictId())) {
        step.and(Tables.BASE_WAREHOUSE.DISTRICT_ID.eq(warehouseCondition.getDistrictId()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getAddress())) {
        likeValue.setLength(0);
        likeValue.append("%").append(warehouseCondition.getAddress()).append("%");
        step.and(Tables.BASE_WAREHOUSE.ADDRESS.like(likeValue.toString()));
    }

    if (!Objects.isNull(warehouseCondition.getWarehouseLnglat())) {
        step.and(Tables.BASE_WAREHOUSE.WAREHOUSE_LNGLAT.eq(warehouseCondition.getWarehouseLnglat()));
    }

    if (StringUtils.isNotBlank(warehouseCondition.getContactName())) {
        step.and(Tables.BASE_WAREHOUSE.CONTACT_NAME.eq(warehouseCondition.getContactName()));
    }
    if (StringUtils.isNotBlank(warehouseCondition.getContactPhone())) {
        step.and(Tables.BASE_WAREHOUSE.CONTACT_PHONE.eq(warehouseCondition.getContactPhone()));
    }
    return step.fetchInto(BaseWarehouse.class);
}




 private Collection<SelectField<?>> getListField() {
    Collection<SelectField<?>> fields = new ArrayList<>();
    fields.add(SHIPMENT.SHIPMENT_ID);
    fields.add(SHIPMENT.OUTBOUND_ID);
    fields.add(SHIPMENT.BIZ_TYPE);
    fields.add(SHIPMENT.BIZ_SUBTYPE);
    fields.add(SHIPMENT.PICKUP_NAME);
    fields.add(SHIPMENT.PICKUP_CONTACT_NAME);
    fields.add(SHIPMENT.PICKUP_CONTACT_PHONE);
    fields.add(SHIPMENT.PICKUP_PROVINCE_NAME);
    fields.add(SHIPMENT.PICKUP_CITY_NAME);
    fields.add(SHIPMENT.PICKUP_DISTRICT_NAME);
    fields.add(SHIPMENT.PICKUP_ADDRESS);
    fields.add(SHIPMENT.DESTINATION_NAME);
    fields.add(SHIPMENT.DESTINATION_CONTACT_NAME);
    fields.add(SHIPMENT.DESTINATION_CONTACT_PHONE);
    fields.add(SHIPMENT.DESTINATION_PROVINCE_NAME);
    fields.add(SHIPMENT.DESTINATION_CITY_NAME);
    fields.add(SHIPMENT.DESTINATION_DISTRICT_NAME);
    fields.add(SHIPMENT.DESTINATION_ADDRESS);
    fields.add(SHIPMENT.DESTINATION_REMARK);
    fields.add(SHIPMENT.ORDER_ID);
    fields.add(SHIPMENT.ORDER_CREATED_AT);
    fields.add(SHIPMENT.STATUS);
    fields.add(DSL.ifnull(SHIPMENT_SKU.SHIPMENT_ID.count(), 0).as("COUNT"));
    fields.add(DSL.ifnull(SHIPMENT_SKU.SKU_COUNT.sum(), BigDecimal.ZERO).as("SKU_COUNT"));
    fields.add(DSL.ifnull(SHIPMENT_SKU.OUTBOUND_COUNT.sum(), BigDecimal.ZERO).as("OUTBOUND_COUNT"));
    fields.add(DSL.ifnull(SHIPMENT_SKU.SIGN_COUNT.sum(), BigDecimal.ZERO).as("SIGN_COUNT"));

    fields.add(SHIPMENT.PICKUP_LNGLAT);
    fields.add(SHIPMENT.DESTINATION_LNGLAT);
    fields.add(SHIPMENT.EXPECT_ARRIVE_BEGIN_AT);
    fields.add(SHIPMENT.EXPECT_ARRIVE_END_AT);
    fields.add(SHIPMENT.BIZ_JSON);
    fields.add(SHIPMENT.WAREHOUSE_ID);
    fields.add(SHIPMENT.DRIVER_REMARK);

    //detail使用字段
    fields.add(SHIPMENT.DRIVER_ID);
    fields.add(SHIPMENT.CUSTOMER_SERVICE);
    fields.add(SHIPMENT.CARRIER_ID);
    fields.add(SHIPMENT.CARRIER_NAME);
    fields.add(SHIPMENT.ROUTE_ID);

    return fields;
}
Result<Record> records = dsl.select(getListField())
        .from(SHIPMENT)
        .leftJoin(SHIPMENT_SKU)
        .on(SHIPMENT.SHIPMENT_ID.eq(SHIPMENT_SKU.SHIPMENT_ID))
        .where(getListConditions(query))
        .groupBy(SHIPMENT.SHIPMENT_ID)
        .orderBy(SHIPMENT.CREATED_AT.desc())
        .offset(query.getOffset())
        .limit(query.getLimit())
        .fetch();

 

DSLContext executeUpdate

   dsl.executeUpdate(dsl.newRecord(BASE_WAREHOUSE, baseWarehouse)), 如果vo类中的主键为null的时候

  

  要指定 condition

  

 

乐观锁实现

  https://www.jooq.org/doc/3.10/manual-single-page/#optimistic-locking

  https://www.jooq.org/doc/3.10/manual-single-page/#codegen-config-record-version-timestamp-fields

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
安全 前端开发 Java
基于springboot的微信公众号管理系统(支持多公众号接入)
基于springboot的微信公众号管理系统(支持多公众号接入)
700 2
|
算法 Java 开发工具
Magisk模块:Audio HeadQuarter(使用前仔细阅读)
Magisk模块:Audio HeadQuarter(使用前仔细阅读)
2012 0
|
SQL 消息中间件 分布式计算
Flink 面试指南 | 终于要跟大家见面了,我有点紧张。(附思维导图)
面试,一个令人大多数同学头疼的问题,要么成功进入心仪公司,要么沮丧与其失之交臂。但是,如果能在面试前就能知道面试官将会问的问题,然后可以好好提前准备,这种感觉是不是特别棒?
Flink 面试指南 | 终于要跟大家见面了,我有点紧张。(附思维导图)
|
机器学习/深度学习 数据采集 数据挖掘
Python | 机器学习之数据清洗
Python | 机器学习之数据清洗
705 0
|
自然语言处理 Prometheus 监控
基于DeepSeek的智能客服系统实战:从开发到部署
本文详细介绍如何将基于DeepSeek的智能客服系统从开发到部署,涵盖服务器选择、环境配置、代码部署及Web服务器设置。通过具体案例和代码示例,讲解系统上线步骤,并介绍使用Prometheus、Grafana等工具进行性能监控的方法。此外,针对高并发、API调用失败等常见问题提供解决方案,确保系统的稳定运行。最后强调数据安全与隐私保护的重要性,帮助读者全面掌握智能客服系统的部署与维护。
|
JavaScript
Vue3弹性布局(Flex)
这是一个基于 Vue 的弹性布局组件库,提供了丰富的参数配置,如宽度、方向、换行等,支持自定义对齐方式和间隙设置。在线预览展示了不同布局效果,包括单选、按钮和滑动输入条等组件的使用示例。
747 0
Vue3弹性布局(Flex)
|
人工智能 Java Spring
Spring框架下,如何让你的日志管理像‘AI’一样智能,提升开发效率的秘密武器!
【8月更文挑战第31天】日志管理在软件开发中至关重要,不仅能帮助开发者追踪问题和调试程序,还是系统监控和运维的重要工具。在Spring框架下,通过合理配置Logback等日志框架,可大幅提升日志管理效率。本文将介绍如何引入日志框架、配置日志级别、在代码中使用Logger,以及利用ELK等工具进行日志聚合和分析,帮助你构建高效、可靠的日志管理系统,为开发和运维提供支持。
441 0
|
JSON JavaScript 中间件
Express.js:构建轻量级Node.js应用的基石
**Express.js 概览**:作为Node.js首选Web框架,Express以其轻量、灵活和强大的特性深受喜爱。自2009年以来,其简洁设计和丰富中间件支持引领开发者构建定制化应用。快速开始:使用`express-generator`创建项目,安装依赖,启动应用。示例展示如何添加返回JSON消息的GET路由。Express适用于RESTful API、实时应用等多种场景,社区支持广泛,助力高效开发。
413 1
|
存储 算法 Linux
使用 bzip2 进行文件压缩和解压缩
`bzip2` 是 Linux 中用于压缩和解压缩的命令,提供比传统方法更好的压缩效果。要压缩文件,使用 `bzip2 filename`(-k 保留原文件),解压缩则用 `bzip2 -d` 或 `bunzip2`。`bzcat` 或 `bzip2 -dc` 可查看压缩文件内容。`-1` 到 `-9` 选项可调整压缩级别(默认为 6)。注意备份重要文件,处理大文件时检查磁盘空间。