【JavaWeb学习Day17】

news/2025/2/22 5:34:47

Tlias智能学习系统(员工管理)

新增员工:

三层架构职责:

Controller:1.接收请求参数(员工信息);2.调用service方法;3.响应结果。

具体实现:

/**
 *新增员工
 */
@PostMapping
public Result save(@RequestBody Emp emp){
    log.info("新增员工:{}",emp);
    empService.save(emp);
    return Result.success();
​
}

Service:1.保存员工基本信息;2.批量保存员工的工作经历信息。

具体实现:

@Override
    public void save(Emp emp) {
        //1.保存员工的基本信息
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp);
​
        //2.保存员工的工作经历信息
        List<EmpExpr> exprList = emp.getExprList();
        if(!CollectionUtils.isEmpty(exprList)){
            //遍历集合,为empId赋值
            exprList.forEach(empExpr -> {
                empExpr.setEmpId(emp.getId());
            });
            empExprMapper.insertBatch(exprList);//Batch批量保存
        }
    }

Mapper:

-- 新增员工
-- 保存员工基本信息 emp
insert into emp(username, name, gender, phone, job, salary, image, entry_date, dept_id, create_time, update_time)
    values ('linpingzhi','林平之',1,'13309091234',1,600,'1.jpg','2020-01-01',1,'2024-10-01 00:00:00','2024-10-01 00:00:00');
-- 保存员工工作经历信息 emp_expr
insert into emp_expr(emp_id, begin, end, company, job)
    values (37,'2020-01-01','2021-01-01','百度','java开发'),(37,'2021-01-01','2022-01-01','字节','java开发');

具体实现:

EmpMapper:

    /**
     * 新增员工基本信息
     * @param emp
     */
    @Options(useGeneratedKeys = true,keyProperty = "id") //获取到生成的主键 -- 主键返回
    @Insert("insert into emp(username, name, gender, phone, job, salary, image, entry_date, dept_id, create_time, update_time)" +
            "    values (#{username},#{name},#{gender},#{phone},#{job},#{salary},#{image},#{entryDate},#{deptId},#{createTime},#{updateTime})")
    void insert(Emp emp);

EmpExprMapper:

/**
 * 批量插入员工工作经历信息
 */
void insertBatch(List<EmpExpr> exprList);

批量插入员工的工作经历用到配置文件(动态SQL):

EmpExprMapper.xml:

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpExprMapper">
<!--    批量保存员工工作经历-->
    <insert id="insertBatch">
        insert into emp_expr(emp_id, begin, end, company, job) values
            <foreach collection="exprList" item="expr" separator=",">
                (#{expr.empId},#{expr.begin},#{expr.end},#{expr.company},#{expr.job})
            </foreach>
    </insert>
</mapper>

动态SQL:<foreach>属性说明:

1.collection:集合名称

2.item:集合遍历出来的元素/项

3.separator:每一次遍历使用的分隔符

4.open:遍历开始前拼接的片段

5.close:遍历结束后拼接的片段

事务管理:

问:保存员工的基本信息成功了,而保存工作经历失败了,是否OK?

答:不可以,因为这是属于一个业务操作,如果保存员工信息成功了,保存工作经历信息失败了,就会造成数据库数据的不完整、不一致。

介绍&操作:

概念:事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作,要么同时成功,要么同时失败。

(注意:默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。)

操作:事务控制主要三步操作:开启事务、提交事务/回滚事务。

-- 开启事务
start transaction; / begin;
​
-- 1. 保存员工基本信息
insert into emp values (39, 'Tom', '123456', '汤姆', 1, '13300001111', 1, 4000, '1.jpg', '2023-11-01', 1, now(), now());
​
-- 2. 保存员工的工作经历信息
insert into emp_expr(emp_id, begin, end, company, job) values (39,'2019-01-01', '2020-01-01', '百度', '开发'),                                                                                                       (39,'2020-01-10', '2022-02-01', '阿里', '架构');
​
-- 提交事务(全部成功)
commit;
​
-- 回滚事务(有一个失败)
rollback;

Spring事务管理:

注解:@Transactional

作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

位置:业务(service)层的方法上、类上、接口上(推荐使用在方法上)

@Transactional //事务管理 - 默认出现运行时异常RunTimeException才会回滚
@Override
public void save(Emp emp) {
    //1.保存员工的基本信息
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.insert(emp);
​
    //2.保存员工的工作经历信息
    List<EmpExpr> exprList = emp.getExprList();
    if(!CollectionUtils.isEmpty(exprList)){
        //遍历集合,为empId赋值
        exprList.forEach(empExpr -> {
            empExpr.setEmpId(emp.getId());
        });
        empExprMapper.insertBatch(exprList);//Batch批量保存
    }
}

事务进阶:

1.rollbackFor属性用于控制出现何种异常类型,回滚事务。

@Transactional(rollbackFor = {Exception.class}) //事务管理 所有异常都回滚

2.事务传播行为(propagation):指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。

@Transactional(propagation = Propagation.REQUIRED)

案例:新增员工信息,记录日志(propagation)

需求:在新增员工信息时,无论是成功还是失败,都要记录操作日志。

步骤:1.准备日志表emp_log、实体类Emplog、Mapper接口EmpLogMapper;2.在新增员工时记录日志

@Transactional(rollbackFor = {Exception.class}) //事务管理 - 默认出现运行时异常RunTimeException才会回滚
@Override
public void save(Emp emp) {
    try{
        //1.保存员工的基本信息
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp);
​
        //2.保存员工的工作经历信息
        List<EmpExpr> exprList = emp.getExprList();
        if(!CollectionUtils.isEmpty(exprList)){
            //遍历集合,为empId赋值
            exprList.forEach(empExpr -> {
                empExpr.setEmpId(emp.getId());
            });
            empExprMapper.insertBatch(exprList);//Batch批量保存
        }
​
    }finally {
        //记录操作日志
        EmpLog empLog = new EmpLog(null,LocalDateTime.now(),"新增员工"+emp);
        empLogService.insertLog(empLog);
​
    }
​
​
}
@Service
public class EmpLogServiceImpl implements EmpLogService {
​
    @Autowired
    private EmpLogMapper empLogMapper;
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void insertLog(EmpLog empLog) {
        empLogMapper.insert(empLog);
    }
}

四大特性(ACID):

原子性Atomicity:事务是不可分割的最小单元,要么全部成功,要么全部失败

一致性Consistency:事务完成时,必须使所有的数据都保持一致状态

隔离性Isolation:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行

持久性Durability:事务一旦提交或回滚,他对数据库中的数据的改变就是永久的

文件上传:

简介:

文件上传:是指将本地的图片、视频、音频等文件上传到服务器,供其他用户浏览或者下载的过程。

文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。

本地存储:

@Slf4j
@RestController
public class UploadController {
    @PostMapping("/upload")
    public Result upload(String name, Integer age, MultipartFile file) throws IOException {
        log.info("接收到的参数:{},{},{}",name,age,file);
        //获取原始文件名
        String originalFileName  = file.getOriginalFilename();
​
​
        //新的文件名
        String extension = originalFileName.substring(originalFileName.lastIndexOf("."));
        String newFileName = UUID.randomUUID().toString() + extension;
​
        //保存文件
        file.transferTo(new File("D:\\xxzl\\java\\file\\"+originalFileName));
         return Result.success();
    }
}

(注意:上传文件大小受限去设置yml文件)

spring:
    servlet:
        multipart:
            #最大单个文件大小
            max-file-size: 10MB
            #最大请求大小(包括所有文件和表单数据)
            max-request-size: 100MB

阿里云OSS:

阿里云:阿里云是阿里巴巴集团旗下全球领先的云计算公司,也是全球最大的云服务提供商。

阿里云OSS:阿里云对象存储OSS(Object Storage Service),是一款海量、安全、低成本、高可靠的云储存服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

第三方服务-通用思路:准备工作->参照官方SDK编写入门程序->集成使用

(SDK:Software Development Kit的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包),示例代码等,都可以叫SDK)

阿里云OSS—使用步骤:

准备工作:注册阿里云(实名认证)->充值->开通对象存储服务OSS->创建bucket->获取并配置AccessKey(密钥)

(Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间)

入门程序:

package com.itheima;
​
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
​
import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.file.Files;
​
public class Demo {
​
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "java-ai";
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "001.jpg";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-beijing";
​
        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)
            .build();
​
        try {
            File file = new File("C:\\Users\\deng\\Pictures\\1.jpg");
            byte[] content = Files.readAllBytes(file.toPath());
​
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

阿里云OSS-案例集成:

1.引入阿里云OSS文件上传工具类(由官方的示例代码改造而来)

package com.itheima.utils;
​
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
​
@Component
public class AliyunOSSOperator {
​
    private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
    private String bucketName = "java-ai-0770";
    private String region = "cn-beijing";
​
    public String upload(byte[] content, String originalFilename) throws Exception {
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
​
        // 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。
        //获取当前系统日期的字符串,格式为 yyyy/MM
        String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));
        //生成一个新的不重复的文件名
        String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = dir + "/" + newFileName;
​
        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
​
        try {
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
        } finally {
            ossClient.shutdown();
        }
​
        return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }
​
}

2.上传文件接口开发

@Autowired
private AliyunOSSOperator aliyunOSSOperator;
@PostMapping("/upload")
public Result upload(MultipartFile file) throws Exception {
    log.info("文件上传:{}",file.getOriginalFilename());
    //将文件交给OSS存储管理
    String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename());
    log.info("文件上传OSS,url:{}",url);
    return Result.success(url);
}

参数配置化:

指将一些需要灵活变化得参数,配置在配置文件中,然后通过@Value注解来注入外部配置得属性。

#阿里云OSS
aliyun:
  oss:
    endpoint: https://oss-cn-beijing.aliyuncs.com
    bucketName: java-ai-0770
    region: cn-beijing
@Value("${aliyun.oss.endpoint}")
private String endpoint ;
@Value("${aliyun.oss.bucketName}")
private String bucketName ;
@Value("${aliyun.oss.region}")
private String region ;

使用@Value注解注入配置文件得配置项,如果配置项多,注入繁琐,不便于维护管理和复用。使用@ConfigurationProperties

@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSProperties {
    private String endpoint;
    private String bucketName;
    private String region;
}
@Autowired
private AliyunOSSProperties aliyunOSSProperties;

		String endpoint = aliyunOSSProperties.getEndpoint();
        String bucketName = aliyunOSSProperties.getBucketName();
        String region = aliyunOSSProperties.getRegion();


http://www.niftyadmin.cn/n/5861646.html

相关文章

RFID测温技术:电力设备安全监测的新利器

在当今高度依赖电力的现代化社会中&#xff0c;稳定且可靠的电力供应是社会运转的基石。电力设备作为电力系统的关键核心&#xff0c;其运行状态直接关乎电力供应的品质。然而&#xff0c;电力设备长期运行过程中&#xff0c;受到诸如过载、接触不良以及环境因素等多重影响&…

HBase性能优化秘籍:让数据处理飞起来

HBase性能优化秘籍&#xff1a;让数据处理飞起来 数据处理太慢&#xff1f;别担心&#xff0c;这里有解决方案&#xff01; 你是否遇到过这样的情况&#xff1a;随着数据量的不断增加&#xff0c;HBase的查询和写入速度变得越来越慢&#xff1f;别担心&#xff0c;今天我们就…

PTT 票据传递攻击

黄金票据 原理&#xff1a;获取 krbtgt 的哈希后&#xff0c;使用此哈希能离线生成任意域用户的 tgt&#xff0c;域管理员的 tgt 就是黄金票据。 mimikatz.exe "privilege::debug" "lsadump::dcsync /domain:HACK.com /user:HACK\krbtgt /csv" "exit…

H5--开发适配

在 H5 开发中&#xff0c;适配不同设备和屏幕尺寸至关重要&#xff0c;它能确保页面在各种环境下都有良好的显示效果和用户体验。以下介绍几种常见的 H5 开发适配方案&#xff1a; 视口&#xff08;Viewport&#xff09;设置 视口单位是相对于浏览器视口的尺寸进行度量的单位&…

【论文阅读】identifying backdoor data with optimized scaled prediction consistency

https://zhuanlan.zhihu.com/p/17155805706 后门秘密被揭开&#xff1a;用优化的尺度预测一致性识别后门数据 先前的后门防御策略主要集中在识别带有后门的模型或被污染数据的特征&#xff0c;通常假设能够访问到干净的数据。本文深入探讨了一个相对未被充分研究的挑战&#x…

istio介绍补充以及使用篇

istio介绍补充以及使用篇 前言 介绍istio各个组件创建istio的方式手动注入自动注入side car 使用istio做流量灰度如有需要收藏的看官&#xff0c;顺便也用发财的小手点点赞哈&#xff0c;如有错漏&#xff0c;也欢迎各位在评论区评论&#xff01; 前言 前篇istio介绍了引入ist…

DeepSeek 提示词:定义、作用、分类与设计原则

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

跳跃游戏II(力扣45)

这道题在跳跃游戏(力扣55)-CSDN博客 的基础上需要找到最小的跳跃次数。那么我们需要用一个变量来统计跳跃次数&#xff0c;而难点就在于何时让该变量的值增加。这一点我写在注释中&#xff0c;大家结合我的代码会更好理解。其他部分跟跳跃游戏(力扣55)-CSDN博客 几乎相同&#…