主要写一些学到的知识
开发规范
开发规范-REST
基于前后端的开发,所以现在都是基于REST风格的api接口来进行交互
什么是REST风格呢?
- REST(Representational State Transfer),表述性状态转换,它是一种软件架构风格。
REST风格的URL,通过四种请求方式来进行增删改查
-
GET : 查询
-
POST :新增
-
PUT :修改
-
DELETE :删除
开发规范-统一响应结果
前后端工程进行交互时,需要统一响应结果Result
Result类包含
code //响应码:1代表成功,0代表失败
msg //响应信息,描述字符串:比如"发送成功"
data //后端返回前端的数据;
开发流程
查看页面原型明确需求,编写接口文档,前端需要后端响应的接口;
阅读接口文档
思路分析
功能接口开发
功能接口测试
前后端联调
分页查询
PageHelper
PageHelper是Mybatis的一款功能强大、方便易用的分页插件,支持任何形式的单标、多表的分页查询。
select * from emp 语句,怎么能够实现分页操作呢?
先获取到要执行的SQL语句:select * from emp
把SQL语句中的字段列表,变为:count(*)
执行SQL语句:select count(*) from emp //获取到总记录数
再对要执行的SQL语句:select * from emp 进行改造,在末尾添加 limit ? , ?
执行改造后的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>
- 例如在mapper层中
@Mapper
public interface EmpMapper {
//获取当前页的结果列表
@Select("select * from emp")
public List<Emp> page(Integer start, Integer pageSize);
}
- 在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
简单使用步骤
页面点击控制台-->搜索"OSS管理控制台"-->开通对象存储服务OSS-->点击左侧"Bucket列表",创建一个Bucket-->注意将读写权限设置为"公共读"
左侧列表找到SDK下载
在java-对象/文件-上传文件-简单上传中-找到上传文件流
- 修改代码
在以上代码中,需要替换的内容为:
accessKeyId:阿里云账号AccessKey
accessKeySecret:阿里云账号AccessKey对应的秘钥
bucketName:Bucket名称
objectName:对象名称,在Bucket中存储的对象的名称
filePath:文件路径
- 获取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)
使用
- 要想使用JWT令牌,需要先引入JWT的依赖
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
- 调用工具包中提供的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令牌,并且把令牌返回给前端。
引入JWT工具类
- 在项目工程下创建utils包,并把提供JWT工具类复制到该包下
登录完成后,调用工具类生成JWT令牌并返回
- 创建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;
}
}
- 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 : 异常后通知,此注解标注的通知方法发生异常后执行
使用
- 在pom.xml中导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 自定义注解
/**
* 自定义Log注解
*/
@Target({ElementType.METHOD})//主要用于方法中
@Documented
@Retention(RetentionPolicy.RUNTIME)//在方法运行时
public @interface Log {
}
- service层业务方法上添加@Log注解
@Override
@Log
public void update(Emp emp) {
emp.setUpdateTime(LocalDateTime.now()); //更新修改时间为当前时间
empMapper.update(emp);
}
- 定义切面类,完成操作
@Aspect //切面类
@Around("@annotation(com.itheima.anno.Log)")//环绕通知
//annotation切入点:主要用来决定项目中的哪些方法需要加入通知
//本段代码表示在Log注解这为切入点