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.学习架构代码和代码摆放 可以看这个视频
简单的一些模版
3学习一下相关一下调度流程的代码
反射的学习
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 对象在访问嵌套属性时自动创建嵌套路径。也就是说,如果某个嵌套路径上的属性为 null,BeanWrapper 会自动创建相应的对象实例,以便访问或设置嵌套属性。
例如,使用以下代码片段: 复制
beanWrapper.setAutoGrowNestedPaths(true);
beanWrapper.setPropertyValue("person.address.city", "New York");
如果 person 或 address 为 null,BeanWrapper 将会自动创建它们。这样,你就可以直接设置 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>
日志打印规范
日志环绕
@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的
异常的统一处理方式
@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);
}
}
}
}
}
}
电商架构的学习
脚手架
加密方案:
各种网站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 包冲突解决方案
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 方法
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