java学习 项目篇 一

学习地址:https://www.bilibili.com/video/BV1TP411v7v6?p=6&spm_id_from=pageDriver&vd_source=a6f7db332f104aff6fadf5b3542e5875

后端环境搭建

在这里插入图片描述

  • Entity 实体,通常和数据库的表对应
  • DTO 数据传输对象,用于程序中各层之间传递数据 (前端发过来)
  • VO 视图对象,为前端展示数据提供的对象,返回前端
  • POJO 普通java对象,只有属性和对应的getter和setter
Swagger使用

常用注解
在这里插入图片描述

一些优雅的方案

  • BeanUtils.copyProperties(a,b)将a对象上的值复制给b对象。

  • Budiler 在定义数据类的时候加上该注解,在创建实例的时候可以使用链式调用。

@Data
@Builder
@ApiOperation(value = "查询返回数据")
public class EmpPageVO {
   Integer count;
   List<Employee> data;
}
// 使用
EmpPageVO empPageVO = EmpPageVO.builder().count(allCount).data(returnData).build();
  • ThreadLocal,每个线程都会创建一个,互不影响,可以将每次请求的用户信息存储起来,后面需要用到直接取出来,因为每个请求都是一个单独的线程,互不影响。
定义类
// spring boot 每个请求都由一个线程处理
public class UserContext {
    public static ThreadLocal<UserContextDTO> threadLocal = new ThreadLocal();

    public static void setCurrentUser(UserContextDTO user){
        threadLocal.set(user);
    }

    public static UserContextDTO getCurrentUser(){
        return threadLocal.get();
    }

    public static void removeCurrentUser(){
        threadLocal.remove();
    }
}

// 将用户信息存储
@Slf4j
@Component("AuthInterceptor")
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
        String url = req.getRequestURL().toString();
        log.info("处理请求....{}", url);

        // TODO 前期不需要校验
        if(url != null){
            // 登陆接口不需要校验
            return true;
        }
        String token = req.getHeader("token");
        try {
            if(token != null){
                Claims data = JwtUtils.parseToken(token);
                UserContext.setCurrentUser((UserContextDTO) data); //将登陆用户存储起来
                return true;
            }else {
                throw new UserNotLoginException("token is not exists or expire");
            }
        } catch (Exception e){
            Result error = Result.error(e.getMessage());
            res.addHeader("Content-Type", "application/json");
            // 转位json
            res.getWriter().write(JSONObject.toJSONString(error));
            return false;
        }
    };
}

//在后续service层可直接使用
 emp.setUpdateUser(UserContext.getCurrentUser().getUserId());
公共字段自动填充
自动填充time,user

像每个表的createTime createUser updateTime updateUser,在每一次增加或者修改的时候都会赋值,为了避免冗余,方便后期维护,可以使用切面AOP,精准拦截对应的方法,然后加上对应的操作,这样原本的create update方法就不用写setCreateTime, setUpdateTime这些了。

在这里插入图片描述

自定义注解
package com.sky.demo.annotaion;

import com.sky.demo.constant.SqlActionType;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AutoFill {
    SqlActionType value();
}


package com.sky.demo.constant;

public enum SqlActionType {
    Update,
    Insert
}

在需要用到的mapper上添注解
在这里插入图片描述
自定义切面类

package com.sky.demo.ascept;


import com.sky.demo.constant.AutoFillConstant;
import com.sky.demo.constant.SqlActionType;
import com.sky.demo.utils.DateTimeFormat;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.sky.demo.annotaion.AutoFill;

import java.lang.reflect.Method;

/**
 * aop,用于给数据库创建 插入 自动注入 时间,用户
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.demo.mapper.*.*(..)) && @annotation(com.sky.demo.annotaion.AutoFill)")
    public void autoFillPointCut(){}

    /**
     * 前置通知
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进行公共字段填充");
        // 获取当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取拦截mapper的注解
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
        // 获取注解的value
        SqlActionType sqlActionType = autoFill.value();
        // 获取到当前被拦截方法的参数-实体对象(categoryMapper.update(data))中的data,修改其参数可以反馈到sql语句中
        Object[] args = joinPoint.getArgs();
        if(args == null || args.length == 0){
            return;
        }
        Object entity = args[0];
        // 准备赋值的数据
        String currentTime = DateTimeFormat.getCurrentTime();

        if(sqlActionType == SqlActionType.Insert){
            try {
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.setCreateUser, Integer.class);
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.setCreateTime, String.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.setUpdateUser, Integer.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.setUpdateTime, String.class);
                // 通过反射进行赋值
                setCreateUser.invoke(entity, 0);
                setCreateTime.invoke(entity, currentTime);
                setUpdateUser.invoke(entity, 0);
                setUpdateTime.invoke(entity, currentTime);
            }catch (Exception e){
                e.printStackTrace();
            }
        }else if(sqlActionType == SqlActionType.Update) {
            try {
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.setUpdateUser, Integer.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.setUpdateTime, String.class);
                setUpdateUser.invoke(entity, 0);
                setUpdateTime.invoke(entity, currentTime);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        // 根据不同的操作类型,为对应的属性赋值

    }
}

通过反射拿到每个实例对象(约定每个方法的第一个参数为实例对象)的setCreateUser等方法,然后注入数据,这样就完成对公共字段的自动填充。

自动处理page,pageSize

基础此思路,继续开发一个拦截分页查询方法的切面类,使其自动实现对page,pageSize等处理。
定义自定义注解

package com.sky.demo.annotaion;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AutoPage {
}

在需要用到的地方使用注解
在这里插入图片描述
实现切面类

package com.sky.demo.ascept;

import com.sky.demo.annotaion.AutoFill;
import com.sky.demo.constant.AutoFillConstant;
import com.sky.demo.constant.SqlActionType;
import com.sky.demo.dto.PageDTO;
import com.sky.demo.utils.DateTimeFormat;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class AutoPageAspect {
    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.demo.mapper.*.*(..)) && @annotation(com.sky.demo.annotaion.AutoPage)")
    public void autoFillPointCut() {
    }

    /**
     * 前置通知
     */
    @Before("autoFillPointCut()")
    public void autoPage(JoinPoint joinPoint) {
        log.info("分页查询开始进行公共字段填充");
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }
        PageDTO entity = (PageDTO)args[0];
        try {
            Method setPage = entity.getClass().getDeclaredMethod(AutoFillConstant.setPage, Integer.class);
            Method setPageSize = entity.getClass().getDeclaredMethod(AutoFillConstant.setPageSize, Integer.class);
            Integer page = entity.getPage() != null ? (entity.getPage() == 0 ? 1 : entity.getPage()) : 1;
            Integer pageSize = entity.getPageSize() != null ? entity.getPageSize() : 20;
            Integer start = (page - 1) * pageSize;
            Integer end = page * pageSize;
            // 通过反射进行赋值
            setPage.invoke(entity, start);
            setPageSize.invoke(entity, end);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

如上,通过强制转换,将实例对象转为PageDTO,约定每个分页的DTO都得继承该类,然后通过反射注入即可。
这样就能自动将page,pageSize转为sql中limit正确的参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/711400.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows安装配置CUDA12.5

搞大模型往往都需要GPU加速&#xff0c;本次在家里的PC上安装CUDA来实现GPU加速。 一、环境准备 操作系统&#xff1a;Windows11 23H2 GPU&#xff1a;RTX 4070 Ti Super 显卡驱动&#xff1a;555.99 &#xff08;NVIDIA GeForce 驱动程序 - N 卡驱动 | NVIDIA&#xff09; …

LaDM3IL:多实例学习用于免疫库分类

一个人的免疫组库由某一时间点的大量适应性免疫受体组成&#xff0c;代表了该个体的适应性免疫状态。免疫组库分类和相关受体识别有可能为新型疫苗的开发做出贡献。大量的实例对免疫组库分类提出了挑战&#xff0c;这可以表述为大规模多实例学习 (MMIL&#xff0c;Massive Mult…

C#——只读属性readonly

只读属性readonly 类的字段可以通过一个readonly(只读)表示这个为只读字段&#xff0c;不能被构造函数之外地方进行修改&#xff0c;静态只读字段不能在非静态的构造函数中使用 定义 只读属性的特点&#xff1a; 字段是只读的非静态 只能在非静态方法中进行修改 字段是只读的…

QT小技巧

QT小技巧 滑条的美化 美化前 代码如下 //滑条的美化ui->horizontalSlider->setStyleSheet("QSlider::groove:horizontal {""border:1px solid skyblue;""background-color:skyblue;""height:10px;""border-radius:5px…

勒索病毒剖析

2016年不自己勒索了 卖病毒 让别人勒索 傻瓜式勒索 黑客用的是非对称加密 全世界只有黑客有那把私钥 反向解密不了 传统爆破容易被检测&#xff0c;黑客慢速爆破&#xff0c;利用超级多的僵尸进行试错&#xff0c;慢慢试出来账号密码 因为一般运维设备在防火墙的白名单里&…

SSM 基于大数据技术的创业推荐系统-计算机毕业设计源码02979

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

IS022000认证:食品安全管理的金标准

食品安全是食品行业的命脉&#xff0c;IS022000食品安全管理体系认证作为最权威的认证之一&#xff0c;为企业提供了强有力的保障。要理解IS022000认证的意义&#xff0c;我们需要先了解它与HACCP和IS09001认证的关系。 HACCP&#xff08;Hazard Analysis and Critical Control…

【Webpack】使用 Webpack 构建 Vue3+TS 项目

构建项目目录 tsc --init npm init -yshim.d.ts 文件是一个类型声明文件&#xff0c;用于告诉 TypeScript 编译器如何处理 Vue 的单文件组件&#xff08;SFC&#xff09;和其他自定义模块。为 Vue 的单文件组件和其他非 TypeScript 模块提供类型信息&#xff0c;以便在 TypeScr…

Redis的安装(linux、docker)与其基本的api使用

一、Redis简介 Redis是一个开源的&#xff0c;使用 C 编写&#xff0c;高性能的Key-Value的NoSQL数据库。 SQL &#xff1a;关系型数据库&#xff0c;例如&#xff1a;MySQL&#xff0c;Oracle等等NoSQL &#xff1a;Not Only SQL 不仅仅是SQL&#xff0c;表示是非关系型数据库…

java之mybatis笔记

1 项目创建 1.1 maven设置 1.2 创建项目文件 1.3 配置MyBatis的相关依赖 1.4 配置 MyBatis 创建一个 mybatis-config.xml 配置文件&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org…

【java】指定类,指定package,找到package下面,这个类的所有子类

目录 ■java代码 ■注意 ■运行效果 ■包的结构 ■java代码 package com.sxz.study.reflect;import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List;public class …

观察者模式(大话设计模式)C/C++版本

观察者模式 扩展&#xff1a;观察者模式——委托 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15905936.html #include <iostream> #include <list> #include <memory> #include <string> using namespace std;// Observer类 抽象观…

【Spine学习09】之导入皮肤两种方式[skin]

第一种&#xff1a;明确项目中某个角色是有两套皮肤的情况下 直接导入两套皮肤 1、添加SKIN皮肤指令 2、在ps中-文件-脚本-浏览【打开选中jsx脚本】 3、打开Spine 点击左上角&#xff0c;选择导入数据 就可以看到该角色的两套皮肤啦&#xff01; 第二种&#xff1a;刚开始角…

探索档案未来,尽在ARCHE-2024

2024年第三届上海国际智慧档案展览会暨高峰论坛&#xff08;ARCHE-2024&#xff09;将于2024年6月19日至21日在上海跨国采购会展中心隆重举行。深圳市铨顺宏科技有限公司应邀参展&#xff0c;将以全新形象盛装亮相&#xff0c;展示其在档案管理领域的最新技术和解决方案。 ARC…

2024年【N2观光车和观光列车司机】考试技巧及N2观光车和观光列车司机模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 N2观光车和观光列车司机考试技巧参考答案及N2观光车和观光列车司机考试试题解析是安全生产模拟考试一点通题库老师及N2观光车和观光列车司机操作证已考过的学员汇总&#xff0c;相对有效帮助N2观光车和观光列车司机模…

网络安全形势迫在眉睫!云WAF保护私有云安全!

业务上云面临新的WEB安全挑战 目前&#xff0c;所有的组织都在积极地接受企业的“云”&#xff0c;推进数字化变革。在服务云计算和私有云平台构建中&#xff0c;用户除了要面对各种常见的网络攻击&#xff0c;还需要面对虚拟环境下的非授权访问、虚拟机逃逸和敏感信息泄漏等问…

【Mongodb-01】Mongodb亿级数据性能测试和压测

mongodb数据性能测试 一&#xff0c;mongodb数据性能测试1&#xff0c;mongodb数据库创建和索引设置2&#xff0c;线程池批量方式插入数据3&#xff0c;一千万数据性能测试4&#xff0c;两千万数据性能测试5&#xff0c;五千万数据性能测试6&#xff0c;一亿条数据性能测试7&am…

Java新特性与性能调优

引言 Java不断演进&#xff0c;每个新版本都引入了新的特性和改进&#xff0c;帮助开发者在提高生产力的同时&#xff0c;也能更好地优化程序性能。本文将详细介绍Java新版本中的重要特性&#xff0c;如从Java 8到Java 17&#xff0c;并探讨性能调优的方法&#xff0c;包括JVM调…

Python自动化办公(二) —— 查看文件夹中的PDF文件数量

Python自动化办公&#xff08;二&#xff09; —— 查看文件夹中的PDF文件数量 在日常办公中&#xff0c;我们经常需要统计某个文件夹中的PDF文件数量。手动操作不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;使用Python可以轻松实现这个过程。本文将介绍如何使用…

【字符串函数2】

5. strncpy 函数的使用和模拟实现 选择性拷贝 char * strncpy ( char * destination, const char * source, size_t num ); 1.拷贝num个字符从源字符串到目标空间。 2.如果源字符串的⻓度⼩于num&#xff0c;则拷⻉完源字符串之后&#xff0c;在⽬标的后边 追加0 &#…