SpringBoot 框架-搭建一套完整的增、删、改、查、上传、下载的样例代码
从上一篇文章: SpringBoot框架代码的编写—以@RequestParam和@RequestBody为例,选取@RequestBody的方式作为例子,编写一套完整的增、删、改、查、上传、下载六大基本功能的样例代码。如果是第一次看到这个文章的朋友需要动手的话,建议先把SpringBoot专栏中这两篇文章先看一遍,并跑通一遍流程。
1、准备数据库环境
因为demo数据库在前面的文章就已经创建了,我就不多说了。直接上本文章中用到的表的建表语句:
create table User(
userid int auto_increment primary key,
username varchar(50) ,
gender varchar(10),
phone varchar(13),
UNIQUE KEY username(username)
) DEFAULT CHARSET=utf8;
insert into user(userid,username,gender,phone) values(1,'张三','男','12345678910');
2、entity层
实体层。这里写的是实体类的定义,数据表中的每个字段名都作为实体类中的一个成员变量,然后这里再实现每个成员变量的get和set的方法。
以demo数据库中的User表为例子,可知userid的类型是int,username、gender和phone的类型是varchar,那么就可以跟着这个类型编写它的代码样例了。
在entity文件夹下创建一个User.java文件夹,定义User表的每一列,并创建setter和getter,代码样例如下:
package com.example.demo.entity;
public class User {
private int userid;
private String username;
private String gender;
private String phone;
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
3、controller层
控制层。控制层中定义了提供给前端的接口的路径,前端使用本接口的方法(GET还是POST),以及需要传输的参数。前端发送来的请求首先传到 “控制器” 中,这里接受前端传来的请求,并将这个请求传到service层(调用了service层的接口)。
在controller文件夹下创建一个SixController.java文件,并写入样例代码:
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.entity.upload;
import com.example.demo.service.impl.ISixService;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@RestController
@RequestMapping(value = "/Six")
public class SixController {
@Autowired
private ISixService iSixService;
String result_insert = "";
int code_500 = 500;
String result_delete = "";
String result_update = "";
String result_select = "";
// 添加新顾客
@RequestMapping(value = "/insert", method = RequestMethod.POST)
private String insert_customer(@RequestBody User u){
try {
int code_insert = iSixService.insert(u.getUserid(),u.getUsername(),u.getGender(),u.getPhone());
if(code_insert == 1) {
int code = 200;
String message = "添加新用户成功";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", code);
jsonObject.put("message", message);
result_insert = jsonObject.toString();
}
}
catch (Exception e){
String insert_e = e.getCause().toString();
if(insert_e.contains("for key 'PRIMARY'") ){
String message = "userid已存在";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code_500);
jsonObject.put("message",message);
result_insert = jsonObject.toString();
}
else if(insert_e.contains("for key 'username'") ){
String message = "用户名已存在";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code_500);
jsonObject.put("message",message);
result_insert = jsonObject.toString();
}
else{
return insert_e;
}
}
return result_insert;
}
@RequestMapping(value = "/delete",method = RequestMethod.POST)
private String delete(@RequestBody User u){
int delete_message = iSixService.delete(u.getUserid());
if(delete_message==0){
int code=200;
String message = "该用户不存在,删除无意义";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_delete = jsonObject.toString();
}
else if(delete_message==1){
int code=200;
String message = "该用户存在,删除成功";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_delete = jsonObject.toString();
}
return result_delete;
}
@RequestMapping(value = "/update",method = RequestMethod.POST)
private String update(@RequestBody User u){
int update_message = iSixService.update(u.getUsername(),u.getUserid());
if(update_message==0){
int code=200;
String message = "更新操作成功,但更新了0条数据";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_update = jsonObject.toString();
}
else if(update_message==1){
int code=200;
String message = "更新成功";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_update = jsonObject.toString();
}
return result_update;
}
@RequestMapping(value = "/select",method = RequestMethod.POST)
private String select(@RequestBody User u) {
User user = iSixService.select(u.getUserid());
if(user!=null){
int code=200;
String message = "该用户存在";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_select = jsonObject.toString();
}
else{
int code = 500;
String message = "该用户不存在";
JSONObject jsonObject = new JSONObject();
jsonObject.put("code",code);
jsonObject.put("message",message);
result_select = jsonObject.toString();
}
return result_select;
}
//上传
@RequestMapping(value = "/upload", method = RequestMethod.POST)
private upload<String> upload(@RequestParam("file") MultipartFile file){
return iSixService.upload(file);
}
// 下载
@RequestMapping(value = "/download", method = RequestMethod.POST)
private void download_order(HttpServletResponse response) {
String result = "D:\\demo.csv";
try {
// path是指想要下载的文件的路径
File file = new File(result);
// 获取文件名
String filename = file.getName();
// 获取文件后缀名
String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
// 将文件写入输入流
FileInputStream fileInputStream = new FileInputStream(file);
InputStream fis = new BufferedInputStream(fileInputStream);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.setCharacterEncoding("UTF-8");
//Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
//attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
// filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
// 告知浏览器文件的大小
response.addHeader("Content-Length", "" + file.length());
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
outputStream.write(buffer);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、service.impl
IMPL,implement的缩写。该层定义了相关service的接口,只是接口,实现接口的代码放在其上层文件夹Service中。接受从控制层controller中传递过来的请求,然后将请求传递给DAO层。
在impl文件夹下创建一个ISixService.java文件,并写入样例代码。
package com.example.demo.service.impl;
import com.example.demo.entity.User;
import com.example.demo.entity.upload;
import org.springframework.web.multipart.MultipartFile;
public interface ISixService {
int insert(int userid,String username,String gender,String phone);
int delete(int userid);
int update(String username,int userid);
User select(int userid);
upload<String> upload(MultipartFile file);
}
5、service
服务层。service接口的实现。在这里调用了DAO接口,将需要操作数据库的请求传递给DAO层。
在service文件夹下创建一个SixService.java文件,并写入样例代码。
package com.example.demo.service;
import com.example.demo.dao.SixDao;
import com.example.demo.entity.User;
import com.example.demo.entity.upload;
import com.example.demo.service.impl.ISixService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@Service
public class SixService implements ISixService {
@Autowired
private final SixDao sixDao;
public SixService(SixDao sixDao) {
this.sixDao = sixDao;
}
@Override
public int insert(int userid,String username,String gender,String phone) {
return sixDao.insert(userid,username,gender,phone);
}
@Override
public int delete(int userid) {
return sixDao.delete(userid);
}
@Override
public int update(String username,int userid) {
return sixDao.update(username,userid);
}
@Override
public User select(int userid) {
return sixDao.select(userid);
}
@Override
public upload<String> upload(MultipartFile file) {
//需要生成几位
int n = 10;
//最终生成的字符串
String str = "";
for (int i = 0; i < n; i++) {
str = str + (char)(Math.random()*26+'a');
}
if(file.isEmpty()) {
return upload.fail("400","文件为空!");
}
String OriginalFilename = file.getOriginalFilename();
String fileName = str + System.currentTimeMillis() + "." + OriginalFilename.substring(OriginalFilename.lastIndexOf(".")+1);
String filepath = "D:\\";
File dest = new File(filepath + fileName);
if(!dest.getParentFile().exists()) {
dest.getParentFile().mkdir();
}
try {
file.transferTo(dest);
}
catch (Exception e) {
e.printStackTrace();
upload.fail("500",OriginalFilename+"上传失败!");
}
return upload.success(fileName);
}
}
6、dao
数据库对后端服务的接口层。接受来自服务层service的请求,将请求传递给mapper。如果是@RequestParam方式的话,则@Param(“username”)中的username以及@Param(“password”)中的password对应的是mapper层中#{}中的参数。@RequestBody亦是如此。
在dao文件夹下创建一个SixDao.java文件,并写入样例代码:
package com.example.demo.dao;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
@Mapper
public interface SixDao {
@Autowired(required = false)
int insert(@Param("userid") int userid,@Param("username") String username,@Param("gender") String gender,@Param("phone") String phone);
int delete(@Param("userid") int userid);
int update(@Param("username") String username,@Param("userid") int userid);
User select(@Param("userid") int userid);
}
7、mapper
数据库操作层,这里写SQL语句,实现dao接口,接受dao接口传入的参数并执行SQL语句操作数据库。
在mapper文件夹下创建一个SixMapper.xml文件,并写入样例代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.demo.dao.SixDao">
<resultMap id="BaseResultMap" type="com.example.demo.entity.User">
</resultMap>
<insert id="insert" parameterType="com.example.demo.entity.User">
insert into user
(userid,username,gender,phone)
values(#{userid},#{username},#{gender},#{phone})
</insert>
<delete id="delete" parameterType="com.example.demo.entity.User">
delete from user where userid=#{userid}
</delete>
<update id="update" parameterType="com.example.demo.entity.User">
update user set username=#{username} where userid=#{userid}
</update>
<select id="select" resultMap="BaseResultMap" parameterType="com.example.demo.entity.User">
SELECT * from User where userid=#{userid}
</select>
</mapper>
8、upload工具类
upload工具类是为了方便上传功能的实现而创建的。
在entity文件夹中创建upload.java文件,并写入样例代码:
package com.example.demo.entity;
public class upload<E> {
private String code;
private String message;
private E body;
public upload(String code, String message, E body) {
this.code = code;
this.message = message;
this.body = body;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public E getBody() {
return body;
}
public void setBody(E body) {
this.body = body;
}
public static <E> upload<E> success(E body) {
return new upload("200","上传成功!",body);
}
public static <E> upload<E> fail(String code, String message) {
return new upload("200",message,(Object) null);
}
}
9、项目结构
10、请求在各层的处理过程
其中,增删改查都是以操作数据库为主,所以这四个接口都经过了层层传递的。
而上传和下载暂时不涉及数据库,只是普通文件的上传下载,所以并不经过dao层和mapper层。
11、效果展示
运行,成功无报错后:
11.1、增
打开postman,选择post方式,在链接中写入http://127.0.0.1:8888/Six/insert,然后选择Body下的raw(以json的格式),填写key-value的json格式,然后点击send。
接口insert,其作用为:给demo数据库的user表添加一条数据。在这我贴一下正确流程后得到的返回结果:
11.2、删
选择post方式,在链接中写入http://127.0.0.1:8888/Six/delete,然后选择Body下的raw(以json的格式),填写key-value的json格式,然后点击send。
接口delete,其作用为:删除demo数据库的user表中userid为2的数据。在这我贴一下正确流程后得到的结果:
11.3、改
选择post方式,在链接中写入http://127.0.0.1:8888/Six/update,然后选择Body下的raw(以json的格式),填写key-value的json格式,然后点击send。
接口update,其作用为:给demo数据库的user表更新userid为1的username为老六。在这我贴一下正确流程后得到的返回结果:
11.4、查
选择post方式,在链接中写入http://127.0.0.1:8888/Six/select,然后选择Body下的raw(以json的格式),填写key-value的json格式,然后点击send。
接口select,其作用为:查询demo数据库中user表中userid为1的客户。在这我贴一下正确流程后得到的返回结果:
11.5、上传
选择post方式,在链接中写入http://127.0.0.1:8888/Six/upload,然后选择Body下的form-data,key这里我在代码里定义为“file”,value这里选择任何一个文件,在这我选择了一个音乐,然后点击send。
接口upload,其作用为:上传文件到D盘的根目录(代码定位放在D盘的根目录),命名格式为随机字母10位加当前毫秒数。在这我贴一下正确流程后得到的返回结果:
11.6、下载
选择post方式,在链接中,写入http://127.0.0.1:8888/Six/download,然后直接点击Send and Download。然后就会出现弹框放置下载的位置,定义后就可以下载指定文件(代码中定义下载的文件,比如样例代码中是下载 D:\demo.csv 文件)。
然后代码流程成功的话会弹出选择框定义存放的位置,比如我选择放在桌面,然后就可以看到已经下载到桌面了:
好了,今天的分享就到此为止。
分享不易,建议一键三连再走。