SpringBootWeb案例

主要写一些学到的知识

开发规范

开发规范-REST

基于前后端的开发,所以现在都是基于REST风格的api接口来进行交互

什么是REST风格呢?

  • REST(Representational State Transfer),表述性状态转换,它是一种软件架构风格。

REST风格的URL,通过四种请求方式来进行增删改查

  • GET : 查询

  • POST :新增

  • PUT :修改

  • DELETE :删除

开发规范-统一响应结果

前后端工程进行交互时,需要统一响应结果Result

Result类包含

code //响应码:1代表成功,0代表失败

msg //响应信息,描述字符串:比如"发送成功"

data //后端返回前端的数据;

开发流程

  1. 查看页面原型明确需求,编写接口文档,前端需要后端响应的接口;

  2. 阅读接口文档

  3. 思路分析

  4. 功能接口开发

  5. 功能接口测试

  6. 前后端联调

分页查询

PageHelper

PageHelper是Mybatis的一款功能强大、方便易用的分页插件,支持任何形式的单标、多表的分页查询。

官网:MyBatis 分页插件 PageHelper

select * from emp 语句,怎么能够实现分页操作呢?

  1. 先获取到要执行的SQL语句:select * from emp

  2. 把SQL语句中的字段列表,变为:count(*)

  3. 执行SQL语句:select count(*) from emp //获取到总记录数

  4. 再对要执行的SQL语句:select * from emp 进行改造,在末尾添加 limit ? , ?

  5. 执行改造后的SQL语句:select * from emp limit ? , ?

使用

1.在pom.xml中引入依赖、

<dependency>

<groupId>com.github.pagehelper</groupId>

<artifactId>pagehelper-spring-boot-starter</artifactId>

<version>1.4.2</version>

</dependency>

  1. 例如在mapper层中

@Mapper

public interface EmpMapper {

//获取当前页的结果列表

@Select("select * from emp")

public List<Emp> page(Integer start, Integer pageSize);

}

  1. 在service层中

@Override

public PageBean page(Integer page, Integer pageSize) {

// 设置分页参数

PageHelper.startPage(page, pageSize); //page是当前是多少页,pageSize是当前页展示多少数据;

// 执行分页查询

List<Emp> empList = empMapper.list(page,pageSize);//调用mapper层的查询;

// 获取分页结果

Page<Emp> p = (Page<Emp>) empList; //将查询的结果变为分页查询

//封装PageBean

PageBean pageBean = new PageBean(p.getTotal(), p.getResult());

//p.getTotal()是得到分页查询的总数

//p.getReslt()是得到分页查询的结果

return pageBean;

}

4.controller层中

//调用业务层分页查询功能

PageBean pageBean = empService.page(page, pageSize);

//page是当前是多少页,pageSize是当前页展示多少数据;

文件上传

使用现有的云服务来存贮文件:如图片

阿里云OSS

简单使用步骤

  1. 打开阿里云官网阿里云-计算,为了无法计算的价值 (aliyun.com)

  2. 页面点击控制台-->搜索"OSS管理控制台"-->开通对象存储服务OSS-->点击左侧"Bucket列表",创建一个Bucket-->注意将读写权限设置为"公共读"

  3. 左侧列表找到SDK下载

在java-对象/文件-上传文件-简单上传中-找到上传文件流

  1. 修改代码

在以上代码中,需要替换的内容为:

  • accessKeyId:阿里云账号AccessKey

  • accessKeySecret:阿里云账号AccessKey对应的秘钥

  • bucketName:Bucket名称

  • objectName:对象名称,在Bucket中存储的对象的名称

  • filePath:文件路径

  1. 获取AccessKey:点击右上角的头像就会出现AccessKey管理

实际项目中使用

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

@Component //用于加入springboot容器中,方便后面自动注入

//需要修改

bucketName

accessKeyId

accessKeySecret为自己的

java 复制代码
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Component
public class AliOSSUtils {
    private String endpoint = "https://oss-cn-shanghai.aliyuncs.com";
    private String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";
    private String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";
    private String bucketName = "web-framework01";

    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile multipartFile) throws IOException {
        // 获取上传的文件的输入流
        InputStream inputStream = multipartFile.getInputStream();

        // 避免文件覆盖
        String originalFilename = multipartFile.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;

        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }
}

controller层中

@Autowired

private AliOSSUtils aliOSSUtils;

@PostMapping("/upload")

public Result upload(MultipartFile image) throws IOException {

//调用阿里云OSS工具类,将上传上来的文件存入阿里云

String url = aliOSSUtils.upload(image);

//将图片上传完成后的url返回,用于浏览器回显展示

return Result.success(url);

}

配置文件

参数配置化

在我们之前编写的程序中进行文件上传时,需要调用AliOSSUtils工具类,将文件上传到阿里云OSS对象存储服务当中。而在调用工具类进行文件上传时,需要一些参数:

  • endpoint //阿里云OSS域名

  • accessKeyID //用户身份ID

  • accessKeySecret //用户密钥

  • bucketName //存储空间的名字

我们可以将参数配置在配置文件中,为了方便后面修改阿里云的参数

则阿里云工具类则由

变为

yml配置文件

application.properties

server.port=8080

server.address=127.0.0.1

application.yml

server:

port: 8080

address: 127.0.0.1

yml格式的数据有以下特点:

  • 容易阅读

  • 容易与脚本语言交互

  • 以数据为核心,重数据轻格式

@ConfigurationProperties

就是更加简化参数的配置化

@ConfigurationProperties注解,并通过perfect属性来指定配置参数项的前缀

将原来的配置由

变为

登录校验--JWT令牌

JWT全称:JSON Web Token (官网:JSON Web Tokens - jwt.io

使用

  1. 要想使用JWT令牌,需要先引入JWT的依赖

<!-- JWT依赖-->

<dependency>

<groupId>io.jsonwebtoken</groupId>

<artifactId>jjwt</artifactId>

<version>0.9.1</version>

</dependency>

  1. 调用工具包中提供的API来完成JWT令牌的生成和校验----工具类:Jwts

测试生成一个

@Test

public void genJwt(){

Map<String,Object> claims = new HashMap<>();

claims.put("id",1);

claims.put("username","Tom");

String jwt = Jwts.builder()

.setClaims(claims) //自定义内容(载荷)

.signWith(SignatureAlgorithm.HS256, "itheima") //签名算法

.setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期

.compact();

System.out.println(jwt);

}

实际项目中使用

登录成功之后生成JWT令牌,并且把令牌返回给前端。

  1. 引入JWT工具类

    • 在项目工程下创建utils包,并把提供JWT工具类复制到该包下
  2. 登录完成后,调用工具类生成JWT令牌并返回

  1. 创建JWT工具类
java 复制代码
public class JwtUtils {

    private static String signKey = "itheima";//签名密钥
    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)//指定令牌Token
                .getBody();
        return claims;
    }
}
  1. controller层
java 复制代码
//依赖业务层对象
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp) {
        //调用业务层:登录功能
        Emp loginEmp = empService.login(emp);

        //判断:登录用户是否存在
        if(loginEmp !=null ){
            //自定义信息
            Map<String , Object> claims = new HashMap<>();
            claims.put("id", loginEmp.getId());
            claims.put("username",loginEmp.getUsername());
            claims.put("name",loginEmp.getName());

            //使用JWT工具类,生成身份令牌
            String token = JwtUtils.generateJwt(claims);
            return Result.success(token);
        }
        return Result.error("用户名或密码错误");
    }

事务

事务是一组操作的集合,它是一个不可分割的工作单位。

Transactional注解

@Transactional作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。 如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。

可以在application.yml配置文件中开启事务管理日志,这样就可以在控制看到和事务相关的日志信息了

#spring事务管理日志

logging:

level:

org.springframework.jdbc.support.JdbcTransactionManager: debug

AOP

AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程)

AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行增强(无侵入性: 解耦)

Spring中AOP的通知类型:

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

使用

  1. 在pom.xml中导入依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-aop</artifactId>

</dependency>

  1. 自定义注解

/**

* 自定义Log注解

*/

@Target({ElementType.METHOD})//主要用于方法中

@Documented

@Retention(RetentionPolicy.RUNTIME)//在方法运行时

public @interface Log {

}

  1. service层业务方法上添加@Log注解

@Override

@Log

public void update(Emp emp) {

emp.setUpdateTime(LocalDateTime.now()); //更新修改时间为当前时间

empMapper.update(emp);

}

  1. 定义切面类,完成操作

@Aspect //切面类

@Around("@annotation(com.itheima.anno.Log)")//环绕通知

//annotation切入点:主要用来决定项目中的哪些方法需要加入通知

//本段代码表示在Log注解这为切入点

相关推荐
Estar.Lee15 分钟前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
友友马1 小时前
『 Linux 』网络层 - IP协议(一)
linux·网络·tcp/ip
码老白2 小时前
【老白学 Java】Warshipv2.0(二)
java·网络
HackKong2 小时前
小白怎样入门网络安全?
网络·学习·安全·web安全·网络安全·黑客
vmlogin虚拟多登浏览器2 小时前
虚拟浏览器可以应对哪些浏览器安全威胁?
服务器·网络·安全·跨境电商·防关联
澜世2 小时前
2024小迪安全基础入门第三课
网络·笔记·安全·网络安全
ZZZCY20034 小时前
华为ENSP--IP编址及静态路由配置
网络·华为
EasyCVR5 小时前
私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?
大数据·网络·音视频·h.265
hgdlip5 小时前
主IP地址与从IP地址:深入解析与应用探讨
网络·网络协议·tcp/ip
珹洺5 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode