java学习 项目篇 一

news2024/11/28 1:41:51

学习地址: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正确的参数。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用Keil打开GD32 FPU及使用ARM DSP库

GD32目前支持ARM Cortex-M和RISC-V两种内核系列芯片&#xff0c;其中Cortex-M内核已经支持的有M3、M4、M23、M33、M7&#xff0c;这里面除了M3和M23以外&#xff0c;其他的都带FPU单元。我们知道&#xff0c;FPU在浮点运算速度上有很大的提升&#xff0c;并且只有带FPU才可以使…

服务器权限管理

我们linux服务器上有严格的权限等级&#xff0c;如果权限过高导致误操作会增加服务器的风险。所以对于了解linux系统中的各种权限及要给用户&#xff0c;服务等分配合理的权限十分重要。&#xff08;权限越大&#xff0c;责任越大&#xff09; 1.基本权限 U--user用户,G-group…

板凳------56.Linux/Unix 系统编程手册(下) -- SOCKET 介绍

56.1.概述 socket 是一种IPC方法&#xff0c;允许位于同一主机或使用网络连接起来的不同主机上的应用程序之间交换数据。 UNIX 允许位于同一主机系统上的应用程序之间通信 Internet domain IPv4 and IPV6 // socket 通信方式 1.各个应用程序创建一个socket&#xff0c;socket是…

GraogGNSSLib学习

GraogGNSSLib学习 程序编译环境版本项目编译结果问题 程序编译 GraphGNSSLib 环境版本 程序开源是在ubuntu16.04-kinetic环境跑通的&#xff0c;但是我的环境是UBUNTU20.04&#xff0c;所以&#xff0c;先进行了ROS的安装&#xff0c;因为我的系统是ubuntu20.04所以&#xf…

软考中级|软件设计师-知识点整理

目录 计算机网络概论 计算机系统基础知识 中央处理单元 数据表示 校验码 计算机体系结构 计算机体系结构的发展 存储系统 输入/输出技术 安全性、可靠性与系统性能评测基础知识 加密技术和认证技术 计算机可靠性 程序设计语言基础知识 程序设计语言概述 程序设计…

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

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

南通国际高中有哪些?南通惠立学校高中部校长见面日重磅来袭

惠灵顿&#xff08;中国&#xff09;自2011年成立以来&#xff0c;一直坚持深耕国际与双语教育&#xff0c;拥有丰厚的办学经验。依托于集团化的深厚经验南通惠立学校于2024-2025学年开设9-11年级&#xff0c;这所南通国际高中为高中学生搭建一个集卓越升学成果、强大师资、纯正…

码住!详解时序数据库不同分类与性能对比

加速发展中的时序数据库&#xff0c;基于不同架构&#xff0c;最流行的类别是&#xff1f; 作为管理工业场景时序数据的新兴数据库品类&#xff0c;时序数据库凭借着对海量时序数据的高效存储、高可扩展性、时序分析计算等特性&#xff0c;一跃成为物联网时代工业领域颇受欢迎的…

解决Maven依赖引入不成功的问题

解决Maven依赖引入不成功的问题 确认IntelliJ IDEA中Maven的设置是否正确。 file --> settings --> maven 清除无效的jar&#xff0c;进入本地仓库清除或利用bat工具 以下是bat工具内容&#xff0c;运行即可。【把仓库地址换成你自己的地址进行无效jar包清除】 echo o…

C++:STL容器-->set

使用set容器时需要导入头文件&#xff1a;#include <set> set和multiset区别&#xff1a; set不允许容器中有重复的元素 multiset允许容器中有重复的元素 1. 构造函数 set<T> st; set s(const &st); void printSet(set<int>& s) {for (set<int>…

laravel版本≥ 8.1

laravel10 php ≥ 8.1 且 ≤ 8.3&#xff1f; 8.1 < php < 8.3PHP版本要求在 8.1 到 8.3 之间&#xff0c;包括这两个版本。具体来说&#xff1a;"≥ 8.1" 表示 PHP 的版本至少是 8.1&#xff0c;也就是说 8.1 及以上的版本都可以。 "≤ 8.3" 表示 P…

MBD_入门篇_21_SimulinkSignalAttributes

21.SignalAttributes 21.1 概述 Signal Attributes&#xff0c;信号属性&#xff0c;信号特性。 21.2 回顾常用模块 21.2.1 DataTypeConversion 数据类型转换模块&#xff0c;可以对信号的数据类型进行强制转换。无符号数据与有符号数据相加&#xff0c;我们可以将无符号数据转…

VS2022 使用C++访问 mariadb 数据库

首先,下载 MariaDB Connector/C++ 库 MariaDB Products & Tools Downloads | MariaDB 第二步,安装后 第三步,写代码 #include <iostream> #include <cstring> #include <memory> #include <windows.h>#include <mariadb/conncpp.hpp>…

echarts学习:通过图例事件实现选中后控制多条折线的显隐

1.问题描述 我在工作中遇到了这样一个需求&#xff1a;我们都知道点击echarts折线图的图例&#xff0c;是可以控制折线的显隐的。我现在希望点击某一个图例可以改变多条折线的显隐。 例如在下面这张图中&#xff0c;我将“xxx水位”和“yyy水位”分为一组&#xff1b;将“xxx…

基于vue的游戏网站设计与实现-计算机毕业设计源码02473

摘要 随着计算机科学技术日渐成熟&#xff0c;人们已经深刻认识到了计算机功能的强大&#xff0c;计算机已经进入到了人类社会发展的各个领域&#xff0c;并且发挥着十分重要的作用。通过管理系统在电脑上的应用&#xff0c;人们能更好的管理信息&#xff0c;储存数据。为了能够…

Linux 终端窗口设置为透明

Linux 终端窗口设置为透明 打开终端 右键鼠标 选择Profile Preferences 点击Background 选择 Transparent background 拖动滑条调整透明度 完成。

SQL编程基础常见题型练习

SQL编程基础常见题型练习 1. 基础查询1.1. 基础查询1.2. 简单处理查询结果 2. 条件查询2.1. 基础排序2.2. 基础操作符2.3. 高级操作符 3. 高级查询3.1. 计算函数3.2. 分组查询 4. 多表查询4.1. 子查询4.2. 链接查询4.3. 组合查询 5. 必会的常用函数5.1. 条件函数5.2. 日期函数 …

Nginx实战:故障处理_后端服务正常,nginx偶发502(Bad Gateway)

一、故障场景 用户访问服务偶发报错【502 Bad Gateway】&#xff0c;但是服务后端正常运行。架构如下&#xff1a; #mermaid-svg-4dDszusKEuPgIPlt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4dDszusKEuPgIPlt…

基于51单片机心率计设计

1 绪论1.1 国内外心率计脉搏仪系统研究现状 心率(Heart Rate)是用来描述心跳周期的专业术语,是指心脏每分钟跳动的次数, 它不仅是反映心脏功能强弱的重要标志,也是反映人体运动强度的生理指标。自公元三世纪我国最早的脉学专著《脉经》问世以来,脉学理论得到不断的发展和提…

Elasticsearch 认证模拟题 - 20

一、题目 定义一个 pipeline&#xff0c;并且将 earthquakes 索引的文档进行更新 pipeline 的 ID 为 earthquakes_pipeline将 magnitude_type 的字段值改为大写如果文档不包含 batch_number&#xff0c;增加这个字段&#xff0c;将数值设置为 1如果已经包含 batch_number&…