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 {@Overridepublic 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");// 转位jsonres.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);// 获取注解的valueSqlActionType 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.mzph.cn/news/853188.shtml

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

相关文章

C++ PDF转图片

C PDF转图片#include "include/fpdfview.h" #include <fstream> #include <include/core/SkImage.h>sk_sp<SkImage> pdfToImg(sk_sp<SkData> pdfData) {sk_sp<SkImage> img;FPDF_InitLibrary(nullptr);FPDF_DOCUMENT doc;FPDF_PAGE …

Android采用Scroller实现底部二楼效果

需求 在移动应用开发中&#xff0c;有时我们希望实现一种特殊的布局效果&#xff0c;即“底部二楼”效果。这个效果类似于在列表底部拖动时出现额外的内容区域&#xff0c;用户可以继续向上拖动查看更多内容。这种效果可以用于展示广告、推荐内容或其他信息。 效果 实现后的…

算法01 递推算法及相关问题详解【C++实现】

目录 递推的概念 训练&#xff1a;斐波那契数列 解析 参考代码 训练&#xff1a;上台阶 参考代码 训练&#xff1a;信封 解析 参考代码 递推的概念 递推是一种处理问题的重要方法。 递推通过对问题的分析&#xff0c;找到问题相邻项之间的关系&#xff08;递推式&a…

MFC基础学习应用

MFC基础学习应用 1.基于对话框的使用 左上角为菜单键&#xff08;其下的关于MFC主要功能由IDD_ABOUTBOX决定) 附图 右下角为按钮&#xff08;基本功能由IDD_DIALOG决定,添加按钮使用由左上角的工具箱完成) 附图 2.自行添加功能与按钮//功能代码 void CMFCApplication4Dlg:…

JS基础与高级应用: 性能优化

在现代Web开发中&#xff0c;性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发&#xff0c;深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节流、防抖、重复请求合并等具体技术手段&#xff0…

linux驱动学习(九)之中断

一、中断的实现 对于中断的请求&#xff0c;在linux内核中&#xff0c;有一套标准的接口函数&#xff0c;可以实现中断的响应和处理。 #include <linux/interrupt.h>//1 申请中断 static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler…

flask南京市旅游景点信息可视化-计算机毕业设计源码02941

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对南京市旅游景点信息可视化等问题&#xff0…

使用gtest做cpp的单元测试并可查看代码覆盖率

前言 由于工作需要&#xff0c;要使用googletest做单元测试&#xff0c;本文记录下搭建gtest单元测试环境&#xff0c;并查看代码覆盖率的方法&#xff0c;以备不时之需。 准备工作 编译gtest 克隆gtest源码&#xff1a; git clone https://github.com/google/googletest.g…

QUIC 和 TCP: 深入解析为什么 QUIC 更胜一筹

引言 在过去的三十年里&#xff0c;HTTP&#xff08;超文本传输协议&#xff09;一直是互联网的支柱。我们可以通过 HTTP 浏览网页、下载文件、流式传输电影等。这一协议随着时间的推移已经得到了重大改进。 HTTP 协议是一个应用层协议&#xff0c;它基于 TCP&#xff08;传输…

【git使用一】windows下git下载、安装和卸载

目录 &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;安装git &#xff08;3&#xff09;安装验证 &#xff08;4&#xff09;卸载git &#xff08;1&#xff09;下载安装包 官网下载地址&#xff1a;Git 国内镜像下载地址&#xff1a;CNPM Binaries Mir…

Unity图集

概述 相信在同学们学习过程中&#xff0c;在UI的的使用时候一定经常听说过图集的概念。 Unity有UI的组件&#xff0c;有同学们好奇&#xff0c;那为什么还要使用图集呢&#xff1f; 这就需要提到一个性能优化的问题了&#xff0c;因为过多的UI图片&#xff0c;会大幅增加Dra…

【机器学习】LightGBM: 优化机器学习的高效梯度提升决策树

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 LightGBM: 优化机器学习的高效梯度提升决策树引言一、LightGBM概览二、核心技术…

buildroot编译出错you should not run configure as root

虚拟机版本&#xff1a;ubuntu-22.04.4 问题 buildroot在图形配置后&#xff0c;执行 sudo make开始编译出现以下错误configure: error: you should not run configure as root (set FOenvironment to bypass this check) 在网上看到说在/etc/profile文件中添加以下内容 exp…

火车头采集织梦发布模块插件下载及教程

火车头采集网页数据发布到织梦CMS&#xff08;DeDeCMS&#xff09;系统操作步骤如下&#xff1a; 1. 火车头采集织梦DeDeCMS发布模块下载安装 百度网盘&#xff1a;火车头采集织梦CMS发布插件下载地址 提取码&#xff1a;414h 2. 在火车头采集软件导入织梦De…

MAC系统下安装VUE

下载node.js 点击链接 选择图片中的稳定版本 安装node.js 打开终端&#xff0c;输入 node -v 和 npm -v 显示如上信息表示安装成功 安装vue脚手架&#x1f527; sudo npm install -g vue/cli查看vue版本 vue -V6. 启动项目 1 采用 图形页面方式 控制台输入&#xff…

MySQL 中 Varchar(50) 和 varchar(500) 区别是什么?

一. 问题描述 我们在设计表结构的时候&#xff0c;设计规范里面有一条如下规则: 对于可变长度的字段&#xff0c;在满足条件的前提下&#xff0c;尽可能使用较短的变长字段长度。 为什么这么规定&#xff1f;我在网上查了一下&#xff0c;主要基于两个方面 基于存储空间的考…

C# Winform 用户控件,扩展控件,自定义控件综合实例

Control类是Windows窗体控件的基类&#xff0c;它提供了在 Windows 窗体应用程序中进行可视显示所需的基础结构&#xff0c;可以通过继承来扩展熟悉的用户控件和现有控件的功能。本列介绍三种不同自定义控件以及怎么创建他们。 自定义控件分类 用户控件&#xff1a;基本控件的…

IT入门知识博客文章大纲第二部分《编程语言》(2/10)

目录 IT入门知识博客文章大纲第二部分《编程语言》 1.引言 2.编程语言概述 2.1 编程语言的发展历程 2.2 编程范式 3.常见的编程语言 3.1 Python 3.2 Java 3.3 C 3.4 JavaScript 3.5 Ruby 4.编程语言的选择 4.1 技术需求 4.2 团队技能 4.3 社区和生态系统 4.4 可…

Python也能“零延迟“通信吗?ZeroMQ带你开启高速模式!

目录 1、零基础入门ZeroMQ 🚀 1.1 ZeroMQ简介与安装 1.2 基础概念:Socket类型详解 1.3 实战演练:Hello World示例 2、深入浅出消息模式 🔌 2.1 请求-应答模式( REQ/REP ) 2.2 发布-订阅模式( PUB/SUB ) 2.3 推送-拉取模式( PUSH/PULL ) 3、Python实战ZeroM…

Aptos Builder Jam 亚洲首站|议程公布,无限畅想 Aptos 生态未来

作为一个新兴的 Layer1 公链&#xff0c;Aptos 自诞生之日起的理想便是 “A Layer 1 for everyone” 当 Web3 深陷熊市阴影之时&#xff0c;Aptos 奋力为开发者找到了全新的技术路径&#xff0c;正有 200 项目正在开发&#xff0c;并且已有大量 DeFi 项目落实部署工作&#xff…