目录
4.8配置文件--@ConfigurationProperties
1.准备工作
注意事项
REST是风格,是约定方式,约定不是规定,可以打破。
描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。如: users、emps、book..
开发规范-统一响应结果
前后端交互统一响应结果Result放在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);
}
}
开发流程
- 查看页面原型明确需求
- 阅读接口文档
- 思路分析
- 接口开发
- 接口测试
- 前后端联调
2.部门管理
2.1查询
在DeptController里面接收请求,调用DeptService查询部门,响应数据。
使用日志记录框架记录日志,要定义一个日志记录对象private static Logger log= LoggerFactory.getLogger(DeptController.class);在其他类中如果也需要定义日志记录对象这句代码就比较麻烦,我们可以使用注解@Sjf4j,就可以直接使用log对象的info方法来记录日志。
要限定开发接口的请求方式是GET,可以在@RequestMapping(value = "/depts",method = RequestMethod.GET)指定请求方式为GET。为简化这个注解可以直接用@GetMapping("/depts")限定请求方式为GET,之后也可以使用@PostMapping("/depts")之类的。
开发流程:前端发送请求之后会请求到DeptController的list()方法,在DeptController的list()方法当中会调用DeptService中的list()方法获取数据,在DeptServicer的list()方法中会调用DeptMapper中的list()方法来查询全部的部门信息,DeptMapper接口就会向数据库中发送sql语句查询员工信息,并且将查询的信息封装到List集合当中,返回给Service,Service返回给Controller,Controller拿到数据再返回给前端。
import com.study.pojo.Dept;
import com.study.pojo.Result;
import com.study.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
public class DeptController {
// private static Logger log= LoggerFactory.getLogger(DeptController.class);//记录日志
@Autowired
private DeptService deptService;
//@RequestMapping(value = "/depts",method = RequestMethod.GET)指定请求方式为GET
@GetMapping("/depts")
public Result list() {
log.info("查询全部部门信息");
//调用Service查询部门数据
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
}
在DeptService中:
import com.study.pojo.Dept;
import java.util.List;
public interface DeptService {
/**
* 查询全部部门信息
* @return
*/
List<Dept> list();
}
DeptServiceImpl中:
import com.study.mapper.DeptMapper;
import com.study.pojo.Dept;
import com.study.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
}
DeptMapper中:
import com.study.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface DeptMapper {
/**
* 查询全部部门数据
* @return
*/
@Select("select * from dept")
List<Dept> list();
}
2.2前后端连调
将前端与后端工程都启动起来,然后访问前端工程,通过前端工程来访问后端程序进而对其调试。
2.3删除
2.4新增
修改部门需要先实现根据ID查询部门,在实现修改部门功能。
代码如下:
DeptController:
@Slf4j
@RestController
public class DeptController {
// private static Logger log= LoggerFactory.getLogger(DeptController.class);//记录日志
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
//@RequestMapping(value = "/depts",method = RequestMethod.GET)指定请求方式为GET
@GetMapping("/depts")
public Result list() {
log.info("查询全部部门信息");
//调用Service查询部门数据
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @param id
* @return
*/
@DeleteMapping("/depts/{id}")
public Result deleteById(@PathVariable Integer id) {
log.info("根据id删除部门{"+id+"}");
deptService.deleteById(id);
return Result.success();
}
/**
* 新增部门
*/
@PostMapping("/depts")
public Result add(@RequestBody Dept dept) {
log.info("新增部门:"+dept);
deptService.add(dept);
return Result.success();
}
/**
* 根据id查询部门
*/
@GetMapping("/depts/{id}")
public Result selectById(@PathVariable Integer id) {
log.info("根据id查询部门"+id);
Dept dept=deptService.selectById(id);
return Result.success(dept);
}
/**
* 修改部门
*/
@PutMapping("/depts")
public Result update(@RequestBody Dept dept) {
log.info("更新部门信息"+dept);
deptService.update(dept);
return Result.success();
}
}
DeptService:
public interface DeptService {
/**
* 查询全部部门信息
* @return
*/
List<Dept> list();
/**
* 删除部门
* @param id
*/
void deleteById(Integer id);
/**
* 新增部门
* @param dept
*/
void add(Dept dept);
/**
* 根据id查询部门
* @param id
* @return
*/
Dept selectById(Integer id);
/**
* 修改部门
* @param dept
*/
void update(Dept dept);
}
DeptServiceImpl:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
@Override
public void deleteById(Integer id) {
deptMapper.deleteById(id);
}
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.add(dept);
}
@Override
public Dept selectById(Integer id) {
return deptMapper.selectById(id);
}
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
DeptMapper:
@Mapper
public interface DeptMapper {
/**
* 查询全部部门数据
* @return
*/
@Select("select * from dept")
List<Dept> list();
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
@Insert("insert into dept(name, create_time, update_time) values (#{name},#{createTime},#{updateTime})")
void add(Dept dept);
@Select("select * from dept where id = #{id}")
Dept selectById(Integer id);
@Update("update dept set name=#{name},update_time=#{updateTime} where id=#{id}")
void update(Dept dept);
}
3.员工管理
3.1分页查询
①分析
创建一个响应数据的实体类PageBean
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 分页查询结果分装类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total;//总记录数
private List rows;//数据列表
}
②实现
③PageHelper插件
3.2分页条件查询
在实现查询功能时,不仅仅要实现将数据列表查询显示出来分页展示,还需要根据条件进行查询。
3.3删除员工
实现了批量删除功能也就是实现了删除功能
3.4新增员工
到此为止的员工管理功能代码如下:
EmpController:
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("分页查询,参数:{},{},{},{},{},{}",page,pageSize,name,gender,begin,end);
PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);
return Result.success(pageBean);
}
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids) {
log.info("删除员工,参数:{}",ids);
empService.delete(ids);
return Result.success();
}
@PostMapping
public Result insert(@RequestBody Emp emp) {
log.info("新增员工,参数:{}",emp);
empService.insert(emp);
return Result.success();
}
}
EmpService:
public interface EmpService {
/**
*分页查询以及条件分页查询
* @return
*/
PageBean page(Integer page, Integer pageSize,String name, Short gender, LocalDate begin,
LocalDate end);
/**
* 删除员工
* @param ids
*/
void delete(List<Integer> ids);
/**
* 新增员工
* @param emp
*/
void insert(Emp emp);
}
EmpServiceImpl:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// @Override
// public PageBean page(Integer page, Integer pageSize) {
// //1.获取总记录数
// Long total = empMapper.count();
// //2.获取分页查询结果列表
// Integer start = (page-1)*pageSize;
// List<Emp> empList=empMapper.page(start,pageSize);
// //3.封装PageBean对象并返回
// PageBean pageBean=new PageBean(total,empList);
// return pageBean;
// }
@Override
public PageBean page(Integer page, Integer pageSize,String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page,pageSize);
//2.执行查询
List<Emp> empList=empMapper.list(name,gender,begin,end);
Page<Emp> p=(Page<Emp>) empList;
//3.封装PageBean对象并返回
PageBean pageBean=new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
@Override
public void delete(List<Integer> ids) {
empMapper.delete(ids);
}
@Override
public void insert(Emp emp) {
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
}
}
EmpMapper:
@Mapper
public interface EmpMapper {
/**
* 获取总记录数
* @return
*/
// @Select("select count(*) from emp")
// Long count();
/**
* 分页查询,获取列表数据
* @param start 起始索引
* @param pageSize 展现列表数
* @return
*/
// @Select("select * from emp limit #{start},#{pageSize}")
// List<Emp> page(Integer start,Integer pageSize);
/**
* 员工信息的查询
* @return
*/
//@Select("select * from emp")
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 删除员工
* @param ids
*/
void delete(List<Integer> ids);
/**
* 新增员工
* @param emp
*/
//@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values " +
// "(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
void insert(Emp emp);
}
写SQL的EmpMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.mapper.EmpMapper">
<!-- 新增员工-->
<insert id="insert">
insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values
(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})
</insert>
<!-- 删除员工-->
<delete id="delete">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<!-- 条件查询-->
<select id="list" resultType="com.study.pojo.Emp">
select * from emp
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>
4.文件上传
4.1简介
- 文件上传,是指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。
- 文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。
文件上传前端页面的三要素:
- 必须要定义一个表单,并且在表单里面要要定义一个类型为file的表单项,体现为一个上传文件的按钮
- 表单的提交方式必须是post,因为进行文件上传,文件一般比较大。
- form表单当中,通过enctype属性指定表单的编码格式为multipart/form-data。因为普通默认的编码格式不适合传输大型的二进制文件
如果表单的编码格式选择的是默认的application/x-www-form-urlencoded: The default value.,提交的文件仅仅是文件的文件名,文件的内容没有提交到服务端。
当编码方式为 multipart/form-data时,上传的文件形式,文件内容与文件名均会上传。
实例:
小结:
4.2本地存储
我们提交的文件临时自动存放在临时文件存放目录下,当这次请求响应完成之后临时文件会被自动删除,所以在文件上传时,除了要接收上传的文件,有时还需要将文件保存起来。
代码实例:
@Slf4j
@RestController
public class UploadController {
@RequestMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传:{},{},{}",username,age,image);
//获取原始文件名
String originalFilename = image.getOriginalFilename();
//构造唯一文件名(不重复)
int index=originalFilename.lastIndexOf(".");
String substring = originalFilename.substring(index);
UUID uuid = UUID.randomUUID();
String newFileName = uuid + substring;
//将文件存储在服务器的磁盘目录中
image.transferTo(new File("E:\\JAVA\\测试\\springboot-案例-本地存储\\"+newFileName));
return Result.success();
}
}
这种上传保存方法对文件的大小有限制,必须小于1M,所以需要加上配置信息。
#配置单个文件最大上传大小 spring.servlet.multipart.max-file-size=10MB #配置单个请求最大上传大小(一次请求可以上传多个文件) spring.servlet.multipart.max-request-size=100MB
针对本地存储出现的问题,项目组可以自己搭建一套用于存储的服务器,还可以使用云存储。
4.3阿里云OOS
①准备
云也就是云端,可以理解为互联网 。云服务就是通过互联网对外提供的各种各样服务
第三方服务-通用思路
- 准备工作
- 参照官方SDK编写入门程序
- 集成使用
Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间。
SDK: Software Development Kit的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK。
②入门
参照SDK文档进行文件上传。
在Java中,首先需要安装 SDK,在pom.xml增加配置信息。
对于文件的上传,可以直接复制实例代码到项目当中,然后根据需求修改代码的变量部分。运行之后可以看到文件已经上传到阿里云OSS当中。
package com.study;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// RAM用户的访问密钥(AccessKey ID和AccessKey Secret)。
String accessKeyId = "LTAI5tGxfdS59C6Lz3t82S3N";
String accessKeySecret = "epmq1T4mM66q5jGIT0IVwKvMxE400w";
// 使用代码嵌入的RAM用户的访问密钥配置访问凭证。
CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
// 填写Bucket名称,例如examplebucket。
String bucketName = "myweb-frame01";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "1.jpg";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "C:\\Users\\ye\\Pictures\\喜欢的图\\壁纸(1).jpg";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
③集成
4.4查询回显
4.5修改员工
4.6参数配置化
问题分析:在做项目时,会涉及多个第三方服务等,代码中的参数过多。当参数发生变化时,需要改动参数并重新进行代码的编,将java代码编译成字节码文件再重新运行,比较繁琐。项目中的类很多时,参数比较分散,修改不方便,难以定位。
4.7配置文件--yml配置文件
4.8配置文件--@ConfigurationProperties
当需要注入的value值过多时,操作比较繁琐。可以使用 @ConfigurationProperties注解。