JavaWeb一些开发问题

一、Restful

image-20240303173010252

package com.example.crudtest1.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private Integer code;//响应码,1 代表成功; 0 代表失败private String msg;  //响应信息 描述字符串private Object data; //返回的数据//增删改 成功响应public static Result success(){return new Result(1,"success",null);}//查询 成功响应public static Result success(Object data){return new Result(1,"success",data);}//失败响应public static Result error(String msg){return new Result(0,msg,null);}
}

image-20240303173615490

二、日志输出

项目开发中尽量避免使用sout输出,使用日志输出

private static Logger log = LoggerFactory.getLogger(DeptController.class);//或者使用注解
@Slf4j

三、分页查询

注意sql中limit的第一个参数即可

例如查询第二页,每页展示10条数据

selcet * from emp limit 10,10

3.1、分页查询插件PageHelper

image-20240304105200327

四、文件上传

4.1、前端

前端,必须提供form表单,提交方式为post 必须要有个input框设置为file

image-20240305100101851

enctype 属性值 如果需要文件上传,必须使用multipart/form-data

4.2、后端

后端在spring boot中使用 MultpartFile 且表单项名字前后端一致

image-20240305101123891

4.3、本地存储

前置知识

1、

这是pom.xml配置文件:

Spring Boot 默认的文件上传大小限制是 1MB。如果上传文件过大,可以自行配置:

#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大大小的限制(一次请求中是可以上传多个文件)
spring.servlet.multipart.max-request-size=10MB

2、由于上传的图片可能会出现同名问题,我们需要给一个唯一的标识,这里推荐使用UUID,拼接原始的上传文件名

Controller层

    /** 文件上传* */@PostMapping("/upload")public Result upload(String username, Integer age, MultipartFile image) throws Exception {log.info("文件上传,{},{},{}",username,age,image);//获取原始文件名String originalFilename = image.getOriginalFilename();//构造唯一的文件名(不能重复)--uuid(通用唯一识别码) a758f47d-8807-4d50-af22-5b4b3208f193int index = originalFilename.lastIndexOf(".");String extname = originalFilename.substring(index);String newFileName = UUID.randomUUID().toString()+extname;log.info("新的文件名:{}", newFileName);//将文件存储在服务器磁盘下image.transferTo(new File("G:\\笔记\\Java\\project\\" +"springboot-mybatis-crudTest\\crudTest1\\image\\"+newFileName));return Result.success();}

4.4、阿里云OSS存储

流程

image-20240305105327660

image-20240305105356731

  • 登录阿里云->控制台->oss基础服务

image-20240305105704801

  • 点击Bucket列表->创建bucket->输入名称,创建
  • 获取密钥,点击头像AccessKey管理-创建一个账号
  • 回到oss服务,拉到最下面找到SDK下载,就可以看到官方文档

image-20240305110622701

https://help.aliyun.com/zh/oss/developer-reference/overview-21

引入依赖

<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version>
</dependency>//java9以上<dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>
<dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.3</version>
</dependency>

引入工具类

package com.example.crudtest1.utils;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;/*** 阿里云 OSS 工具类*/
public class AliOSSUtils {private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";private String accessKeyId = "LTAI4GCH1vX6DKqJWxd6nEuW";private String accessKeySecret = "yBshYweHOpqDuhCArrVHwIiBKpyqSL";private String bucketName = "web-tlias";/*** 实现上传图片到OSS*/public String upload(MultipartFile file) throws IOException {// 获取上传的文件的输入流InputStream inputStream = file.getInputStream();// 避免文件覆盖String originalFilename = file.getOriginalFilename();String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//上传文件到 OSSOSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ossClient.putObject(bucketName, fileName, inputStream);//文件访问路径String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;// 关闭ossClientossClient.shutdown();return url;// 把上传到oss的路径返回}}

五、配置文件

优化阿里云配置文件,利用@ConfigurationProperties(prefix = “aliyun.oss”)

image-20240306141945833

image-20240306142118929

这里的属性必须要与yml配置文件里面同名

在AliOSSUtils中利用注解注入

package com.example.crudtest1.utils;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;/*** 阿里云 OSS 工具类*/@Componentpublic class AliOSSUtils {@Autowired
private AliOSSProperties aliOSSProperties;/*** 实现上传图片到OSS*/public String upload(MultipartFile file) throws IOException {String endpoint = aliOSSProperties.getEndpoint();String accessKeyId = aliOSSProperties.getAccessKeyId();String accessKeySecret = aliOSSProperties.getAccessKeySecret();String bucketName = aliOSSProperties.getBucketName();// 获取上传的文件的输入流InputStream inputStream = file.getInputStream();// 避免文件覆盖String originalFilename = file.getOriginalFilename();String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//上传文件到 OSSOSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ossClient.putObject(bucketName, fileName, inputStream);//文件访问路径String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;// 关闭ossClientossClient.shutdown();return url;// 把上传到oss的路径返回}}

5.1、yml配置文件

基本语法

  • 大小写敏感
  • 数值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • #表示注释,从这个字符一直到行尾,都会被解析器忽略
server:port: 9000#定义对象/map集合
user:name:Tomage:18#定义Liset/set集合
hobby:-java-java2spring:#数据库连接datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/tliasusername:password:#文件上传servlet:multipart:max-file-size: 10MBmax-request-size: 100MB#mybatis
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true#阿里云OSS
aliyun:oss:endpoint : "";accessKeyId : "";accessKeySecret : "";bucketName : "";

六、登录校验

会话技术

会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。

会话跟踪

一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

  • 会话跟踪方案:

    客户端会话跟踪技术:Cookie
    • 服务端会话跟踪技术:Session
    • 令牌技术

image-20240306150426478

6.1、JWT令牌

由三个部分组成,由Base64进行编码

  • header(头)
  • Payload(有效载荷)
  • Signature(签名)

image-20240307101015470


在登录成功后,生成令牌,后续每个请求都需要携带令牌,系统在处理请求时,需要先校验令牌

6.1.1、依赖

        <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>

工具类

package com.example.crudtest1.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String signKey = "zyyy";//设置生成时间为12小时private static Long expire = 43200000L;/*** 生成JWT令牌* @param claims JWT第二部分负载 payload 中存储的内容* @return*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return jwt;}/*** 解析JWT令牌* @param jwt JWT令牌* @return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims = Jwts.parser().setSigningKey(signKey).parseClaimsJws(jwt).getBody();return claims;}
}

七、过滤与拦截

过滤器链,由多个过滤器组成,由类文件名A-Z执行

image-20240308220507398

7.2、拦截器

定义拦截器,实现HandlerInterceptor接口,并重写其所有方法

package com.example.crudtest1.interceptor;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //目标资源方法前运行, 返回true 放行,返回false 不放行public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("目标资源方法前运行");
//        return HandlerInterceptor.super.preHandle(request, response, handler);return  true;}@Override //目标资源方法后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);System.out.println("目标资源方法后运行");}@Override //视图渲染完后执行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);System.out.println("视图渲染完后执行");}
}

注册拦截器

package com.example.crudtest1.config;import com.example.crudtest1.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration //配置类
public class WebConfig  implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//要拦截哪些资源 addPathPatterns 
//excludePathPatterns 放行registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");;}
}

image-20240311094631631

执行流程

image-20240311094924883

image-20240311095035214

八、异常处理

全局异常处理器 RestControllerAdvice

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)//捕获全部异常public Result ex(Exception e){e.printStackTrace();return Result.error("操作失败,请联系管理员");}
}

九、事务管理

事务:一组操作集合,不可分割,要么同时成功,要么失败

image-20240311100858289

注解@Transactional

注意 默认情况下只会出现RuntimeException才回滚异常

可以设置rollbackFor 来指定出现何种异常回滚

#spring事务管理日志
logging:level:org.springframework.jdbc.support.JdbcTransactionManager: debug

9.1、传播行为

事务传播行为:指的是一个事务方法被另一个事务调用

image-20240311114041102

10、AOP

AOP:面向切面编程,就是面向特定的方法编程

通过底层的动态代理机制,对特定的方法进行编程

  • 引入依赖
<dependency><groupId>org.springframework.boot</groupId>	<artifactId>spring-boot-starter-aop</artifactId></dependency>

获取每个方法的运行时长

package com.example.crudtest1.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Slf4j
@Component
@Aspect
public class TimeAspect {@Around("execution(* com.example.crudtest1.service..*.*(..))")public Object  recordTime(ProceedingJoinPoint joinPoint ) throws Throwable {//1.记录开始时间long begin = System.currentTimeMillis();//调用原始方法运行Object result = joinPoint.proceed();//记录结束时间,计算方法执行耗时long end = System.currentTimeMillis();log.info(joinPoint.getSignature()+ "方法耗时,{}",end-begin);return  result;}
}

10.1、核心概念

  • 连接点:JoinPoint,可以被AOP控制的方法

image-20240312102046747

  • 通知:Advice,指重复的逻辑,也就是共性功能

image-20240312102055529

  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用

image-20240312102232612

这里表现的是只有list这一个功能点运行时,才会被通知

  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)

image-20240312102418987

  • 目标对象:Target,通知所应用的对象

执行流程

image-20240312104429791

10.2、通知类 image-20240312104719894

@Pointcut 切入点,可以将重复的片段抽取起来统一使用

    @Pointcut("execution(* com.example.crudtest1.service.impl.DeptServiceImpl.*(..))")public  void pt(){};@Before("pt()")public void before(){log.info("before ...");}

不同切面类中,默认按照切面类的类名字母排序:
目标方法前的通知方法:字母排名靠前的先执行
目标方法后的通知方法:字母排名靠前的后执行

可以使用@Order(数字)控制顺序

目标方法前的通知方法:数字越小前的先执行
目标方法后的通知方法:数字越小的后执行

10.3、切入点表达式

  • execution():根据方法的签名来进行匹配

image-20240312123103279

image-20240312123145823书写建议
所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是find开头,更新类方法都是update开头。

描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。

在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用…使用*匹配单个包。

  • @annotation():根据注解匹配

image-20240312123354070

10.4、连接点

JoinPoint抽象了连接点,可以用它获得方法执行时的相关信息,如目标类、方法名、方法参数

注意点:

  • @Around通知,获取连接点信息只能使用ProceedingJoinPoint

  • 其他四种通知,获取连接点信息只能使用JoinPoint

    它是ProceedingJoinPoint的父类型

        //1、获取目标对象的类名String className = proceedingJoinPoint.getClass().getName();log.info("目标对象的类名,{}",className);//2.获取目标方法的方法名String methodName = proceedingJoinPoint.getSignature().getName();log.info("目标对象的类名,{}",methodName);//3.获取目标运行时传入的参数Object[] args = proceedingJoinPoint.getArgs();log.info("目标对象的类名,{}", Arrays.toString(args));//4.放行 目标方法执行Object result = proceedingJoinPoint.proceed();

11.springBoot原理

配置优先级问题

image-20240314170332600

第三方Bean对象

  • 如果要管理的bean对象来自于第三方(不是自定义的),是无法用@Component及衍生注解声明bean的,就需要用到@Bean注解。
  • 若要管理的第三方bean对象,建议对这些bean进行集中分类配置,可以通过@Configuration注解声明一个配置类。

image-20240314172803395

11.1、起步依赖

spring boot 中引入项目依赖不需要那么繁琐,主要靠依赖传递,保证引入项目需要的依赖

11.2、自动配置

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

  • 原理实现

    • @import
    • @EnableXXX注解,封装了@Import(推荐)
  • 源码

    • @SpringBootApplication

      • @SpringBootConfiguration

        • 和configuration注解作用相同,声明当前也是一个配置类
      • @EnableAutoConfiguration

        • 组件扫描,默认扫描当前引导类所在包及其子类
      • @ComponentScan

        • 实现自动化配置的核心注解

条件装配注解

  • Conditional注解
    • 按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中
  • 常用Conditional注解
    • @ConditionalOnClass:判断是否有对应的字节码文件
    • @ConditionalOnMissingBean:判断环境中没有对应的bean才会注入
    • @ConditionalOnProperty:判断配置文件中对应属性和值,才注册bean到IOC容器

11.3、案例(自动starter)

自定义起步依赖-制作阿里云工具类的自动装配

image-20240315120801264

12、maven

12.1、继承与聚合

作用
聚合用于快速构建项目
继承用于简化依赖配置、统一管理依赖

相同点:
聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中聚合与继承均属于设计型模块,并无实际的模块内容

不同点:
聚合是在聚合工程中配置关系,聚合可以感知到参与聚合的模块有哪些继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

12.2、私服

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题。

image-20240316172159637

image-20240316172448902

  • Release:发行版本,功能趋于稳定,当前停止更新
  • snapshot:快照版本,功能不稳定、尚且 处于开发中的版本

步骤

  • 配置本地仓库访问私服的权限,修改maven的conf/settings.xml配置文件,指定访问私服的用户名/密码
<server><id>releases</id><username>admin</username>#这里是私服设置的密码<password>123456</password>
</server>
<server><id>snapshots</id><username>admin</username>#这里是私服设置的密码<password>123456</password>
</server>
  • IDEA中配置要上传项目中的发布管理,修改pom.xml,指定上传的位置
<distributionManagement><repository><id>releases</id><url>http://localhost:8081/repository/maven-releases/</url></repository> <snapshotRepository><id>snapshots</id><url>http://localhost:8081/repository/maven-snapshots/</url></snapshotRepository> 
</distributionManagement>

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

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

相关文章

【现代C++】移动语义和右值引用

现代C++中的移动语义和右值引用是C++11引入的重要特性,旨在优化资源管理和提升性能。这些特性允许资源的转移而非复制,特别是对于临时对象和大型对象。 1. 右值引用 右值引用是对临时对象的引用,它允许你修改临时对象。使用&&来声明右值引用。 #include <iost…

【NTN 卫星通信】 TN和多NTN配合的应用场景

1 场景描述 此场景描述了农村环境&#xff0c;其中MNO (运营商TerrA)仅在城市附近提供本地地面覆盖&#xff0c;而MNO (SatA)提供广泛的NTN覆盖。SatA使用GSO轨道和NGSO轨道上的卫星。SatA与TerrA有漫游协议&#xff0c;允许:   所有TerrA用户的连接&#xff0c;当这些用户不…

论文浅尝 | GPT-RE:基于大语言模型针对关系抽取的上下文学习

笔记整理&#xff1a;张廉臣&#xff0c;东南大学硕士&#xff0c;研究方向为自然语言处理、信息抽取 链接&#xff1a;https://arxiv.org/pdf/2305.02105.pdf 1、动机 在很多自然语言处理任务中&#xff0c;上下文学习的性能已经媲美甚至超过了全资源微调的方法。但是&#xf…

第二十五天-Seaborn数据可视化库

目录 1.介绍 2.使用 1.seaborn官网&#xff1a; 2.安装 3.基础用法 4.导入数据 5.分析基金数据 1.绘制每个月收盘价的趋势线 2.计算涨跌幅 3.设置统计基点 4.分布图&#xff1a;分析涨跌幅数量 5.箱型图 6.回归图 7.热力图 1.介绍 1.与matplotlib区别 2.基于matp…

矩阵中移动的最大次数

文章目录 所属专栏:BFS算法 题目链接 思路如下&#xff1a; 1.首先我们需要从第一列开始遍历&#xff0c;寻找每一个都能够满足条件的位置&#xff0c;将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面&#xff0c;如果数组为空&#…

Tomcat Seeion 集群

部署&#xff1a;nginx服务器&#xff1a;11-11&#xff1b;tomcat1:11-3; tomcat2:11-6 nginx服务器11-11做搭建&#xff1a; [rootmcb-11 ~]# systemctl stop firewalld [rootmcb-11 ~]# setenforce 0 [rootmcb-11 ~]# yum install epel-release.noarch -y [rootmcb…

【C++】类和对象终章

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、初始化列表1.1 初始化列表的形式1.2 初始化列表的注意事项 二、explicit关键…

c++实现简单搜索二叉树<K,V>形

文章目录 搜索二叉树节点类BSTreeNode(节点类的构造) BSTree(功能实现类)Insert(插入)Erase(删除)Find(查找这个节点) 搜索二叉树 搜索二叉树本质:左节点比我小 右节点比我大 节点类 BSTreeNode:给自身节点封装一个类 用这个类来添加节点的操作 我们写的是一个key.value型的搜…

第二十四天-数据可视化Matplotlib

目录 1.介绍 2.使用 1. 安装&#xff1a; 2.创建简单图表 3.图表类型 1.一共分为7类 2.变化 1.折线图 3.分布 ​编辑 1.直方图 2.箱型图 4.关联 1. 散点图&#xff1a; 2.热力图&#xff1a; 5.组成 1.饼图 2.条形图 6.分组 1.簇型散点图 2.分组条形图 3.分…

程序人生——Java多线程和并发的使用建议

目录 引出多线程和并发建议118&#xff1a;不推荐覆写start方法建议119&#xff1a;启动线程前stop方法是不可靠的建议120&#xff1a;不适用stop方法停止线程 建议121&#xff1a;线程优先级只使用三个等级建议122&#xff1a;使用线程异常处理器提升系统可靠性建议123&#x…

主干网络篇 | YOLOv8更换主干网络之ShuffleNetV2

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。ShuffleNetV2是一种轻量级的神经网络架构&#xff0c;用于图像分类和目标检测任务。它是ShuffleNet的改进版本&#xff0c;旨在提高模型的性能和效率。ShuffleNetV2相比于之前的版本&#xff0c;在保持模型轻量化的同时&am…

什么是CRM系统?全面解析,学会利用CRM提升业务效率

在客户心目中&#xff0c;200家CRM企业可能会有200种CRM管理系统&#xff0c;很多客户接触客户经理的第一句话都是&#xff1a;“你家是什么CRM&#xff1f;”。CRM系统是什么&#xff1f;很多技术商、企业管理者自己往往都没有概念&#xff0c;我们通过一文全面解析。简单来说…