Skip to content

2024年6月随笔

GET请求下载Stream文件流资源

浏览器返回的Content-Typeapplicatoin/octet stream类型,也设置了Content-Disposition:,可以使用以下方式下载:

blob方式

js
fetch(url, {
  method: 'GET',
  headers: {
    Authorization: "Bearer " + store.getters.access_token,
  },
  responseType: 'blob',
}).then(res => res.blob())
.then(blob => {
    let a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    let event = new MouseEvent('click');
    a.download = file.name;
    a.dispatchEvent(event);
})

buffer的方式,这里以node的保存文件api为例子

js
fetch(url, {
  method: 'GET',
}).then(res => res.arrayBuffer())
  .then(arrayBuffer => {
    const bufferData = Buffer.from(arrayBuffer);
    fs.writeFile(filePath, bufferData, (err) => {
      if (err) throw err;
      console.log('文件已被保存');
      callback && callback(filePath);
    })
  })

记一次拼装树形结构的方法

原数据如下,需要转化为树形结构

json
[
  {
"id": "350200",
"parentId": "350000",
"name": "厦门市",
"indexUrl": null,
"children": []
},
{
"id": "350203",
"parentId": "350200",
"name": "思明区",
"indexUrl": null,
"children": []
},
{
"id": "350213",
"parentId": "350200",
"name": "翔安区",
"indexUrl": null,
"children": []
},
{
"id": "350303",
"parentId": "350300",
"name": "涵江区",
"indexUrl": null,
"children": []
},
{
"id": "350304",
"parentId": "350300",
"name": "荔城区",
"indexUrl": null,
"children": []
},
{
"id": "350300",
"parentId": "350000",
"name": "莆田市",
"indexUrl": null,
"children": []
}
]

实现方法

java
import java.util.*;  
  
public class TreeBuilder {  
  
    public static List<Map<String, Object>> buildTree(List<Map<String, Object>> list, String rootParentId) {  
        // 创建一个Map来方便查找节点  
        Map<String, Map<String, Object>> map = new HashMap<>();  
        for (Map<String, Object> item : list) {  
            map.put((String) item.get("id"), item);  
        }  
  
        List<Map<String, Object>> tree = new ArrayList<>();  
        for (Map<String, Object> item : list) {  
            String parentId = (String) item.get("parentId");  
            if (parentId.equals(rootParentId)) { // 检查是否是根节点  
                tree.add(addItemToChildren(map, item));  
            }  
        }  
        return tree;  
    }  
  
    private static Map<String, Object> addItemToChildren(Map<String, Map<String, Object>> map, Map<String, Object> item) {  
        String id = (String) item.get("id");  
        List<Map<String, Object>> children = (List<Map<String, Object>>) item.get("children");  
        if (children == null) {  
            children = new ArrayList<>();  
            item.put("children", children);  
        }  
  
        for (Map<String, Object> childItem : map.values()) {  
            String childParentId = (String) childItem.get("parentId");  
            if (childParentId != null && childParentId.equals(id)) {  
                children.add(addItemToChildren(map, childItem)); // 递归处理子节点  
            }  
        }  
        return item;  
    }  
  
    public static void main(String[] args) {  
        // 假设这是你的输入数组  
        List<Map<String, Object>> inputList = ... // 这里放你的数组  
  
        // 调用方法来构建树形结构,这里假设根节点的parentId为"350000"  
        List<Map<String, Object>> tree = buildTree(inputList, "350000");  
  
        // 打印结果,或者按需要进行其他操作  
        System.out.println(tree);  
    }  
}

mybatis-plus查询mysql关键字报错

java
由于`timestamp`是MySQL的保留关键字,直接使用它作为列名可能会导致SQL查询中的错误。在使用MyBatis或MyBatis-Plus时,有几种方法可以避免这个问题。

### 方法一:使用反引号(`)

在SQL中,你可以使用反引号来包围列名,以指示它是列名而不是关键字。但是,MyBatis-Plus的注解`@TableField`本身并不直接支持在注解值中使用反引号。不过,你可以通过自定义SQL映射或使用MyBatis的XML映射文件来确保列名被正确地用反引号包围。

**自定义SQL映射示例**(在Mapper接口中):

```java
@Select("SELECT `timestamp` FROM your_table_name WHERE ...")
List<YourEntity> selectByCustomConditions(...);

MyBatis XML映射文件示例

xml
<select id="selectByCustomConditions" resultType="YourEntity">
    SELECT `timestamp` FROM your_table_name WHERE ...
</select>

方法二:更改列名

如果可能的话,更改数据库中的列名以避免使用关键字是一个更好的长期解决方案。例如,你可以将列名从timestamp更改为my_timestamp或其他非关键字的名称。

方法三:使用MyBatis-Plus的全局配置(如果支持)

某些版本的MyBatis-Plus可能提供了全局配置来自动处理关键字或特殊字符的列名。你可以检查MyBatis-Plus的文档或配置以查看是否有这样的选项。

方法四:使用ResultMap

在MyBatis的XML映射文件中,你可以使用<resultMap>来明确指定Java属性与数据库列之间的映射关系,并在其中使用反引号。

xml
<resultMap id="yourResultMap" type="YourEntity">
    <result column="`timestamp`" property="timestamp" javaType="string"/>
    <!-- 其他字段映射 -->
</resultMap>

<select id="selectByExample" resultMap="yourResultMap">
    SELECT * FROM your_table_name
    <!-- 其他查询条件 -->
</select>

但请注意,直接在<result>标签的column属性中使用反引号可能不是所有MyBatis版本都支持的。你可能需要尝试或查阅相关文档。

方法五:使用MyBatis-Plus的自定义SQL注入器

MyBatis-Plus提供了自定义SQL注入器的功能,允许你自定义插入、更新、查询等操作的SQL。你可以利用这个功能来确保列名被正确地用反引号包围。但是,这通常是一个较高级的功能,需要你对MyBatis-Plus的内部机制有较深的理解。

通过注解的方式实现日志记录

首先声明注解类

java
package com.tyky.itmp.issue.management.annotion;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogRequest {
    String value() default "";
}

创建AOP切面并实现注解类

java
package com.tyky.itmp.issue.management.aop;

import com.alibaba.fastjson.JSONObject;
import com.tyky.itmp.issue.management.api.dto.ApasApiDto;
import com.tyky.itmp.issue.management.service.ApasRequestLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestLoggingAspect {

    @Pointcut("@annotation(com.tyky.itmp.issue.management.annotion.LogRequest)")
    public void logPointcut() {}

    @Autowired
    private ApasRequestLogService apasRequestLogService;

    @Around("logPointcut()")
    public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {

        log.info("记录日志");
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        // 获取请求URL和HTTP方法
        String url = request.getRequestURL().toString();
        String httpMethod = request.getMethod();

        // 获取请求参数名称
        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = discoverer.getParameterNames(method);

        // 获取请求参数值
        Object[] args = joinPoint.getArgs();
        ApasApiDto apasApiDto = (ApasApiDto) args[0];
        // 记录日志信息
        log.info("====开始记录日志====");
        apasRequestLogService.saveLog(null,apasApiDto.getToken(),url,httpMethod, JSONObject.toJSONString(apasApiDto),0);
        log.info("====日志记录完毕====");

        // 继续执行原方法
        Object result = joinPoint.proceed();

        return result;
    }
}

关于node-sass安装报错问题

在开发前端项目时,使用Sass作为CSS预处理器是很多开发者的选择。然而,在通过npm安装其Node.js绑定库node-sass时,一些开发者可能会遇到安装失败的问题,尤其是网络原因导致的下载缓慢或中断。本文将指导你如何通过更换为国内镜像源解决npm install node-sass安装失败的问题。

解决办法:

更换默认仓库为国内镜像

参考地址如下: https://blog.csdn.net/qq_29752857/article/details/139252709

bash
npm config set registry https://registry.npmmirror.com

这会将你的npm默认仓库设置为NPM Mirror,从而加速后续的包下载过程,这是全局切换npm源地址,如果后续有npm发包操作,需要切换回源地址,比较麻烦,并不推荐

指定国内镜像安装node-sass

对比Node.js与node-sass版本

可以先指定node-sass特定版本使用国内镜像安装,然后再全局安装全部的依赖,如果使用了国内镜像最好统一使用安装,这种方式比较推荐

bash
npm install node-sass@^4.14.0 --registry=https://registry.npmmirror.com

npm install --registry=https://registry.npmmirror.com

npm安装gifsicle相关依赖报错问题处理

第一种:Error: Cannot find module 'gifsicle'

原因是对应的模块 image-webpack-loader 未安装好

解决办法:

卸载重新安装,建议用cnpm安装。

  1. 卸载 npm uninstall image-webpack-loader。(用cnpm安装的,就用cnpm卸载)

  2. 安装 cnpm install --save-dev image-webpack-loader

备注:如果上面两步执行了,再npm install 会报其他的错误,网上查了其他错误依旧解决不了,把package-lock.json删掉,node_modules也删掉。再重新试一下npm install。

第二种:Error: Cannot find module 'imagemin-gifsicle'

原因:在下载image-webpack-loader时,他没有找到这些包,所以需要我们自己另外单独去cnpm这些包

解决办法:

安装:cnpm install imagemin-gifsicle@7.0.0,然后重新启动项目;

备注:这一步解决后,可能还会报其他相关错误,依次安装即可。

Error: Cannot find module 'imagemin-mozjpeg',安装cnpm install imagemin-mozjpeg@9.0.0

Error: Cannot find module 'imagemin-pngquant',安装cnpm install imagemin-pngquant@9.0.2

上次更新于: