自己的一些常用的写法记在在这里、方便以后使用

257 阅读7分钟

1. 如果想要 你能写一个通用方法,把这些敏感字段设置为空

juejin.cn/post/715165… 这个泛型可以参考一下

public class ApplicationV3 {
    // 把敏感字段设置为空
    public static <T> T removeField(T obj) throws Exception {
        // 需要过滤的敏感字段
        Set<String> fieldSet = new HashSet<String>();
        fieldSet.add("password");

        // 获取所有字段:然后获取这个类所有字段
        Field[] fields = obj.getClass().getDeclaredFields();

        // 敏感字段设置为空
        for (Field field : fields) {
            if (fieldSet.contains(field.getName())) {
                // 开放字段操作权限
                field.setAccessible(true);
                // 设置空
                field.set(obj, null);
            }
        }

        // 返回对象
        return obj;
    }
}

2.学习架构代码和代码摆放 可以看这个视频

www.bilibili.com/video/BV1PX…

简单的一些模版

3学习一下相关一下调度流程的代码

mp.weixin.qq.com/s/J3zL0PErv…

反射的学习

import java.lang.reflect.Field;
import com.example.MyAnnotation;
#获取字段信息
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
    String fieldName = field.getName();
    System.out.println(fieldName);
}

#获取字段注解
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
    MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
    if (annotation != null) {
        String annotationValue = annotation.value(); // 获取注释中的值
        System.out.println("Field: " + field.getName() + ", Annotation value: " + annotationValue);
    }
}

Spring 直接包装类(可以结合Aop 来使用,直接在模型参数中统一给值)

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

public class Main {
    public static void main(String[] args) {
        // 创建一个 Person 对象
        Person person = new Person();
        
        // 使用 BeanWrapperImpl 包装 Person 对象
        BeanWrapper beanWrapper = new BeanWrapperImpl(person);
        
        // 设置属性值
        beanWrapper.setPropertyValue("name", "John Doe");
        beanWrapper.setPropertyValue("age", 25);
        
        // 读取属性值
        String name = (String) beanWrapper.getPropertyValue("name");
        int age = (int) beanWrapper.getPropertyValue("age");
        
        // 打印属性值
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

beanWrapper.setAutoGrowNestedPaths(true) 是用于设置 BeanWrapper 对象在访问嵌套属性时是否自动创建嵌套路径的配置。

当你使用 BeanWrapper 对象访问一个嵌套属性时,例如 person.address.city,如果嵌套路径中的某个属性为 null,默认情况下会抛出 NullValueInNestedPathException 异常。这是因为在默认设置下,BeanWrapper 不会自动创建嵌套路径,而是要求你在访问嵌套属性之前手动创建每个路径上的对象实例。

但是,通过调用 beanWrapper.setAutoGrowNestedPaths(true),你可以配置 BeanWrapper 对象在访问嵌套属性时自动创建嵌套路径。也就是说,如果某个嵌套路径上的属性为 nullBeanWrapper 会自动创建相应的对象实例,以便访问或设置嵌套属性。

例如,使用以下代码片段: 复制

beanWrapper.setAutoGrowNestedPaths(true);
beanWrapper.setPropertyValue("person.address.city", "New York");

如果 person 或 address 为 nullBeanWrapper 将会自动创建它们。这样,你就可以直接设置 person.address.city 的值,而不需要手动创建 person 和 address 对象。

这种自动创建嵌套路径的配置可以简化代码,特别是在处理深层嵌套对象或动态创建对象时非常有用。但需要注意,在自动创建嵌套路径的情况下,确保在访问嵌套属性之前对对象进行了必要的初始化,以避免空指针异常。

AOP中参数的获取

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Around("execution(* com.example.MyClass.myMethod(..))")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        
        // 获取方法名
        String methodName = signature.getName();
        
        // 获取返回类型
        Class<?> returnType = signature.getReturnType();
        
        // 获取参数类型
        Class<?>[] parameterTypes = signature.getParameterTypes();
        
        // 获取参数名称
        String[] parameterNames = signature.getParameterNames();
        
        // 打印方法信息
        System.out.println("Method Name: " + methodName);
        System.out.println("Return Type: " + returnType);
        System.out.println("Parameter Types: " + Arrays.toString(parameterTypes));
        System.out.println("Parameter Names: " + Arrays.toString(parameterNames));
        
        // 执行目标方法
        Object result = joinPoint.proceed();
        
        // 打印返回结果
        System.out.println("Result: " + result);
        
        
     
        
        // 获取方法参数类型
        Class<?>[] parameterTypes = signature.getParameterTypes();
        
        // 获取方法参数值
        Object[] parameterValues = joinPoint.getArgs();
        
        
     
// 获取目标方法的参数值 通过 `getArgs()` 方法,你可以在切面中获取目标方法的参数值,并在需要的时候进行//相应的处理,比如记录日志、验证参数、修改参数值等等。以下是一个简单示例展示了如何使//用 `getArgs()` 方法获取目标方法的参数值:


        Object[] args = joinPoint.getArgs();

        

        
        return result;
    }
}

分页

import com.github.pagehelper.PageInfo;

// ...

// 设置分页参数
int pageNum = 1; // 当前页数
int pageSize = 10; // 每页显示的记录数
PageHelper.startPage(pageNum, pageSize);

// 执行查询操作
List<YourEntity> resultList = yourService.queryEntities();

// 获取分页信息
PageInfo<YourEntity> pageInfo = new PageInfo<>(resultList);
long total = pageInfo.getTotal(); // 总记录数
int totalPages = pageInfo.getPages(); // 总页数
List<YourEntity> pageData = pageInfo.getList(); // 当前页的数据列表

xml实现

public interface YourEntityMapper {
    List<YourEntity> queryEntities(@Param("offset") int offset, @Param("pageSize") int pageSize);
}

<mapper namespace="com.example.yourpackage.YourEntityMapper">

  <!-- 定义分页查询的 SQL -->
  <select id="queryEntities" resultType="com.example.yourpackage.YourEntity">
    SELECT *
    FROM your_table
    LIMIT #{offset}, #{pageSize}
  </select>

</mapper>

日志打印规范

image.png

日志环绕

@Pointcut("execution(* com.baidu.restservice.controller.. *.* (..))")
public void controller(){}


@Pointcut("execution(* com.baidu.restservice.service.. *.* (..))")
public void domain(){}


@Pointcut("controller()||domain()")
public void allLog(){}


 @Around("allLog()")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable {
  MethodSignature sign = (MethodSignature) joinPoint.getSignature();
    Method method = sign.getMethod();

    // 获取包名
    String packageName = method.getDeclaringClass().getPackage().getName();
    // 获取类名
    String className = method.getDeclaringClass().getSimpleName();
    // 获取方法名
    String methodName = method.getName();
    log.info("入参打印日志 packageName{} className{} methodName{} ",packageName,className,methodName)
   }
    Object[] args = joinPoint.getArgs();
    StandardReflectionParameterNameDiscoverer parameterNameDiscoverer = new StandardReflectionParameterNameDiscoverer();
    String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
    
    String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);

    // 打印每个参数的详细信息
    if (parameterNames != null && parameterNames.length > 0) {
        for (int i = 0; i < parameterNames.length; i++) {
            String parameterName = parameterNames[i];
            Object parameterValue = args[i];
            System.out.println("Parameter Name: " + parameterName + ", Value: " + parameterValue);
        }
    }
   Object result = joinPoint.proceed();

     log.info("入参打印日志 packageName{} className{} methodName{} result{}",packageName,className,methodName,result)




接口上报日志

泛型类中如何获取单个 注入的class

 Type superClass = getClass().getGenericSuperclass();
       
            Type[] typeArgs = ((ParameterizedType) superClass).getActualTypeArguments();
      
        (Class) typeArgs[0]

过滤器拦截Post请求的中参数

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
   private final String body;

   public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
       super(request);
       StringBuilder stringBuilder = new StringBuilder();
       try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
           String line;
           while ((line = bufferedReader.readLine()) != null) {
               stringBuilder.append(line);
           }
       }
       body = stringBuilder.toString();
   }

   @Override
   public ServletInputStream getInputStream() throws IOException {
       return new BodyReaderServletInputStream(body);
   }

   @Override
   public BufferedReader getReader() throws IOException {
       return new BufferedReader(new InputStreamReader(getInputStream()));
   }

   public String getBody() {
       return body;
   }
}
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class BodyReaderFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化过滤器
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(httpRequest);

        // 获取请求的body内容
        String body = requestWrapper.getBody();
        // 在这里可以对body内容进行处理

        // 继续执行过滤链
        filterChain.doFilter(requestWrapper, servletResponse);
    }

    @Override
    public void destroy() {
        // 销毁过滤器
    }
}

泛型使用的方式

public <T> T query(String query, TypeReference<T> t) {
....
return JSONObject.parseObject(value, t);
}
query("123",new TypeReference<List<Map<String, Object>>>() {})

接口多态实现多种方式的管理

public interface i 

public class abstract vehicle {
 public void run();
}

public car end 

泛型接口类型:

R 代表返回类型
public interface IHandler<T,R>{
}

tk.mybatis的用法

public interface CommonMapper<T extends baseEntity> extend 各自读写接口 
然后下游只需要继承这一个接口,就可以符合需求了

枚举类的使用 gpt给的答案

public enum Status {
    ACTIVE(1, "Active"),
    INACTIVE(2, "Inactive"),
    PENDING(3, "Pending");

    private final int code;
    private final String description;

    Status(int code, String description) {
        this.code = code;
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }

    // 从数字到枚举常量的转换
    public static Status fromCode(int code) {
        for (Status status : Status.values()) {
            if (status.getCode() == code) {
                return status;
            }
        }
        throw new IllegalArgumentException("Invalid Status code: " + code);
    }

    // 从枚举常量到数字的转换
    public static int toCode(Status status) {
        return status.getCode();
    }
}

跨域访问

@Configuration
public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")  //指定允许跨域请求的路径模式为"/**",表示所有的路径都将允许跨域访问。
                    .allowedOrigins("*") // 允许访问资源的域名
                    .allowedMethods("*") // 允许的HTTP方法
                    .allowedHeaders("*") // 允许的请求头
                    .allowCredentials(false) // 是否允许发送凭证信息
                    .maxAge(3600); // 预检请求的有效期
        }
}

Springboot3的脚手架搭建

juejin.cn/post/736505… 代码 在我的gitee上fork 了

私活专属 这个用的Springboot3的+vue的

gitee.com/guchengwuyu…

异常的统一处理方式

@Getter
public Enum Status{

 private Integer code;
 private String  msg;
 
 ERROR(100,'xxx);
 

}


public class BizException extend RuntimeException{
  private Integer code;
  private String  msg;
  
  public BizException(Status status){
     super(status.getMsg());
     this.code=status.getCode();
     this.msg=status.getMsg();
  }

}

使用注解来做加密的方式:

Target(ElementType.FIELD)//表示字段级注解
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface  Encryption {
  
  
}

@Aspect
@Componet
public class  EncryptionAscept{

  public void encryption(JoinPoint jpt){
      Object[] args =jpt.getArgs();
      for(Object obj:args){
        if(arg!=null){
          Class<?> objectClass= arg.getClass();
          for(Field field:objectClass.getDeclaredFields){
          
               if(field.isAnnotationPresent(Encryption.class)){
                 field.setAccessible(true);
                 Object obj= field.get(arg);
                  // xx
                  field.set(arg,xx);
                 
               
               }
          
          }
          
        }
      }
  
  }


}

电商架构的学习

skrshop.tech/#/

脚手架

gitee.com/feiyuchuixu…

加密方案:

juejin.cn/post/727555…

各种网站demo

chencoding.top:8090/#/?id=react…

mysql 表默认创建时间和更新时间

CREATE TABLE demo_table (

id INT PRIMARY KEY AUTO_INCREMENT,

data VARCHAR(255),

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

);

jar 包冲突解决方案

www.jianshu.com/p/7a0e20b30…

git 强行覆盖代码

git fetch origin
git reset --hard origin/<远程分支名称>
git clean -df

常用解决方式:
git checkout master
git fetch 
git pull -rebase origin master
git checkout - 
git rebase -i master

 git switch feature-a
 git rebase master

fix conflicts...
$ git rebase --continue


在vscode 或者idea 中
如果使用 merge的方式:
在vscode 中选择 git graph 然后切好到当前分支、然后点击git graph 然后 选择到master 分支(前提是mater 分支的代码已经是最新的了 ,然后点击 merge into current branch 
如果使用 rebase的方式:
则相反 选择到matser 分支上 然后 点击需要的分支然后 点击 Rebase current branch onto 'master'
总结一下:
切好到我们的dev 分支上去、此时main分支已经线上最新的分支的了,最后就用 **`merge into current branch `**  一下 main 分支不会有变化 dev的分支会有合并

然后 




debug 方法

www.bilibili.com/video/BV1xW…

vscode 操作rebase 直接看这个zhuanlan.zhihu.com/p/69286730?…

一般可以县 git log --oneline 命令  找到 commit id 
然后 根据 commit 找到要压缩的 分支区间
然后 用 git rebase - i commit  id 

类似是 
pick xxx 
s xxx


p 是选择保留
s 是选择压缩掉 

具体可以参考 这个 zhuanlan.zhihu.com/p/678878177 这个 git rebase 的时候先切换到fix分支上然后再git rebase master 分枝 git rebase master 就会将fix 分支放到master 后面了

#强行回滚 git reset --hard head git clean -fd 强行远程仓库 git fetch origin &&git reset --hard origin/feat/xxx