SpirngBoot + Vue 前后端分离开发工具代码
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Leo的博客
💞当前专栏: Java从入门到精通
✨特色专栏: MySQL学习
🥭本文内容:SpirngBoot + Vue 前后端分离开发工具代码
🖥️个人小站 :个人博客,欢迎大家访问
📚个人知识库: Leo知识库,欢迎大家访问
1.MybatisPlus配置类
导入依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
package com.jerry.common.config.mp;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** ClassName: MybatisPlusConfig* Package: com.jerry.common.config.mp* Description:** @Author gaoziman* @Create 2023-03-01 11:17* @Version 1.0*/@Configuration
@MapperScan("com.jerry.auth.mapper")
public class MybatisPlusConfig {/*** 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> configuration.setUseDeprecatedExecutor(false);}
}
2.使用mybatisplus分页查询
第一种
/*** 条件分页查询** @param page 当前页* @param pageSize 分页大小* @param sysRoleQueryVo 条件查询对象* @return*/@ApiOperation("条件分页查询")@GetMapping("{page}/{pageSize}")private Result page(@PathVariable int page, @PathVariable int pageSize, SysRoleQueryVo sysRoleQueryVo) {// 1、创建 page 对象, 传递分页查询的参数Page<SysRole> sysRolePage = new Page<>(page, pageSize);// 2、构造分页查询条件, 判断条件是否为空,不为空进行封装LambdaQueryWrapper<SysRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();String roleName = sysRoleQueryVo.getRoleName();if (!StringUtils.isEmpty(roleName)) {// 封装lambdaQueryWrapper.like(SysRole::getRoleName,roleName);}// 3、调用方法实现分页查询sysRoleService.page(sysRolePage, lambdaQueryWrapper);return Result.ok(sysRolePage);}
第二种
@PreAuthorize("hasAuthority('bnt.sysUser.list')")@ApiOperation("条件分页查询")@GetMapping("/page/{pageNum}/{pageSize}")public Result pageQueryUser(@PathVariable Long pageNum,@PathVariable Long pageSize,SysUserQueryVo sysUserQueryVo) {//1 创建Page对象,传递分页相关参数//page 当前页 limit 每页显示记录数Page<SysUser> pageParam = new Page<>(pageNum,pageSize);//2 调用service方法IPage<SysUser> page = userService.selectByPage(pageParam,sysUserQueryVo);return Result.success(page);}
<select id="selectByPage" resultMap="sysUserMap">SELECT * FROM sys_user<where><if test="vo.keyword != '' and vo.keyword != null ">and (username like CONCAT('%',#{vo.keyword},'%')or name like CONCAT('%',#{vo.keyword},'%')or phone like CONCAT('%',#{vo.keyword},'%'))</if><if test="vo.createTimeBegin != null and vo.createTimeBegin !=''">and create_time >= #{vo.createTimeBegin}</if><if test="vo.createTimeEnd !=null and vo.createTimeEnd !=''">and create_time <=#{vo.createTimeEnd}</if>and is_deleted = 0</where></select>
3.统一返回的结果
package com.trs.common.result;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 公共返回对象** @author gaoziman* @date 2022/8/7*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {/*** 状态码*/private Integer code;/*** 提示信息*/private String message;/*** 返回对象*/private Object data;/*** 成功返回结果** @param resultCodeEnum 提示信息* @return 返回成功*/public static Result success(ResultCodeEnum resultCodeEnum) {return new Result(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), null);}/*** 成功返回结果** @param resultCodeEnum 提示信息* @param data 返回数据* @return 返回成功*/public static Result success(ResultCodeEnum resultCodeEnum, Object data) {return new Result(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), data);}/*** 失败返回结果** @param resultCodeEnum 提示信息* @return 返回失败*/public static Result error(ResultCodeEnum resultCodeEnum) {return new Result(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), null);}/*** 失败返回结果** @param message 提示信息* @return 返回失败*/public static Result error(String message) {return new Result(500, message, null);}/*** 失败返回结果** @param resultCodeEnum 提示信息* @param data 返回数据* @return 返回失败*/public static Result error(ResultCodeEnum resultCodeEnum, Object data) {return new Result(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), data);}/*** 失败返回结果** @param message 提示信息* @return 返回失败*/public static Result error(ResultCodeEnum resultCodeEnum, String message) {return new Result(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), null);}/*** 失败返回结果** @param code 状态码* @param message 提示信息* @return 返回失败*/public static Result error(Integer code, String message) {return new Result(code, message, null);}
}
package com.trs.common.result;import lombok.Getter;/*** 统一返回结果状态信息类** @author 高自满*/
@Getter
public enum ResultCodeEnum {SUCCESS(200,"成功"),FAIL(201, "失败"),SERVICE_ERROR(2012, "服务异常"),DATA_ERROR(204, "数据异常"),LOGIN_AUTH(401, "尚未登录,请重新登录"),PERMISSION(209, "没有权限"),LOGIN_MOBLE_ERROR(210,"登录认证失败" ),ACCOUNT_STOP(211,"账号已停用" ),TOKEN_ERR(212,"token异常"),PERMISSION_ERR(403,"权限不足,请联系管理员"),COMMENT_SUCCESS(200,"评论成功,请等待管理员审核" ),COMMENT_SUCCESS_S(200,"评论成功" ),COMMENT_ERROR(501,"评论失败" );private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}
}
4.Redis配置类
导入依赖
<!-- Redis依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
package com.trs.blog.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** Redis配置类** @author : gaoziman* @date 2023/5/2 10:32*/
@Configuration
public class RedisConfig {/*** Redis序列化*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// String类型key序列器redisTemplate.setKeySerializer(new StringRedisSerializer());// String类型value序列器redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());// Hash类型kay序列器redisTemplate.setHashKeySerializer(new StringRedisSerializer());// Hash类型value序列器redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());// 设置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}
5.代码生成器
导入依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.0</version></dependency>
package com.trs.serviceUtil.util;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;/*** @author gaoziman* 代码生成器*/
public class CodeGet {public static void main(String[] args) {// 1、创建代码生成器AutoGenerator mpg = new AutoGenerator();// 2、全局配置// 全局配置GlobalConfig gc = new GlobalConfig();gc.setOutputDir("E:\\exer_code\\cisyam-blog\\blog-parent\\service-blog"+"/src/main/java");gc.setServiceName("%sService"); //去掉Service接口的首字母Igc.setAuthor("manman");gc.setOpen(false);mpg.setGlobalConfig(gc);// 3、数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/blog?serverTimezone=GMT%2B8&useSSL=false");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("root");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);// 4、包配置PackageConfig pc = new PackageConfig();pc.setParent("com.trs");pc.setModuleName("blog"); //模块名pc.setController("controller");pc.setService("service");pc.setEntity("pojo");pc.setMapper("mapper");mpg.setPackageInfo(pc);// 5、策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("week_view");strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作strategy.setRestControllerStyle(true); //restful api风格控制器strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符mpg.setStrategy(strategy);// 6、执行mpg.execute();}
}
6.工具类
拷贝工具类
package com.trs.blog.util;import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.List;/*** 集合对象复制工具类** @author gaoziman* @date 2023/5/1 23:32*/
public class BeanCopyUtil {/*** 复制集合** @param source 复制的原对象集合* @param clazz 对象类型* @param <T> 泛型* @return 复制完成的集合*/public static <T> List<T> copyList(List source, Class<T> clazz) {List<T> target = new ArrayList<>();if (!CollectionUtils.isEmpty(source)) {if (!CollectionUtils.isEmpty(source)) {for (Object c : source) {T obj = copy(c, clazz);target.add(obj);}}}return target;}/*** 复制对象** @param source 复制的原对象* @param clazz 对象类型* @param <T> 泛型* @return 复制完成的新对象*/public static <T> T copy(Object source, Class<T> clazz) {if (source == null) {return null;}T obj = null;try {obj = clazz.newInstance();} catch (Exception e) {e.printStackTrace();}BeanUtils.copyProperties(source, obj);return obj;}/*** 将传来的Object对象转为指定的List集合** @param object 传来的Object对象* @param clazz 指定类型* @param <T> 泛型* @return 指定的List集合*/public static <T> List<T> castObjectToList(Object object, Class<T> clazz) {List<T> result = new ArrayList<>();// 如果传来的对象属于List集合if (object instanceof List<?>) {for (Object o : (List<T>) object) {result.add(clazz.cast(o));}return result;}return null;}
}
集合工具类
package com.trs.blog.util;import org.springframework.util.StringUtils;import java.util.ArrayList;
import java.util.List;/*** 集合工具类** @author gaoziman* @date 2023/5/1 23:32*/
public class CollectionUtil {/*** 将传来的字符串数据转为整型集合** @param str 字符串数据* @return 整型集合*/public static List<Integer> stringToIntegerList(String str) {if (StringUtils.isEmpty(str)) {return null;}// 去除字符串两边的[]str = str.substring(1, str.length() - 1);// 根据 , 进行分割String[] split = str.split(",");List<Integer> result = new ArrayList<>();for (String s : split) {result.add(Integer.parseInt(s));}return result;}
}
IP地址工具类
package com.trs.blog.util;import com.alibaba.fastjson.JSON;
import eu.bitwalker.useragentutils.UserAgent;import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;import static com.trs.common.constant.CommonConst.LOCAL_HOST;/*** IP地址工具类** @author gaoziman* @date 2023/5/1 23:32*/
public class IpUtil {/*** 获取当前IP地址以及IP所属源** @return IP地址*/public static String getCurIpAddress(HttpServletRequest request) {String ipAddress = null;try {ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {// 获取到本机的远程IP地址ipAddress = request.getRemoteAddr();if (LOCAL_HOST.equals(ipAddress)) {// 根据网卡取本机配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress = inet.getHostAddress();}}// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {// = 15if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}} catch (Exception e) {ipAddress = "";}return ipAddress;}/*** 解析ip地址** @param ipAddress ip地址* @return 解析后的ip地址*/public static String getIpSource(String ipAddress) {try {URL url = new URL("http://opendata.baidu.com/api.php?query=" + ipAddress + "&co=&resource_id=6006&oe=utf8");BufferedReader reader = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream(), "utf-8"));String line = null;StringBuffer result = new StringBuffer();while ((line = reader.readLine()) != null) {result.append(line);}reader.close();Map map = JSON.parseObject(result.toString(), Map.class);List<Map<String, String>> data = (List) map.get("data");return data.get(0).get("location");} catch (Exception e) {return "";}}/*** 获取用户的访问设备** @param request 请求* @return 用户访问设备*/public static UserAgent getUserAgent(HttpServletRequest request){return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));}
}
JWT处理Token工具类
package com.trs.blog.util;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** Jwt处理Token工具类* * @author gaoziman* @date 2023/5/1 23:32*/
@Component
public class JwtTokenUtil {/*** 用户名的key*/private static final String CLAIM_KEY_USERNAME = "sub";/*** JWT的创建时间*/private static final String CLAIM_KEY_CREATED = "created";/*** 秘钥*/@Value("${jwt.secret}")private String secret;/*** token失效时间*/@Value("${jwt.expiration}")private Long expiration;/*** 根据用户信息生成token** @param userDetails 用户信息* @return 生成的token*/public String generateToken(UserDetails userDetails) {// 定义token中存储数据的载荷Map<String, Object> claims = new HashMap<>();// 1. 用户名claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());// 2. 签发时间claims.put(CLAIM_KEY_CREATED, new Date());// 签发tokenreturn generateToken(claims);}/*** 根据载荷生成token** @param claims 载荷* @return 生成的token*/private String generateToken(Map<String, Object> claims) {return Jwts.builder()// 1. 设置载荷.setClaims(claims)// 2. 设置失效时间.setExpiration(generateExpirationDate())// 3. 设置签名.signWith(SignatureAlgorithm.HS512, secret)// 签发token.compact();}/*** 生成token失效时间** @return token的失效时间*/private Date generateExpirationDate() {// token失效时间:当前系统时间 + 自己定义的时间return new Date(System.currentTimeMillis() + expiration * 1000);}/*** 从token中获取用户名** @param token token* @return 当前token中存储的用户名*/public String getUserNameFromToken(String token) {String userName;try {// 从token中获取到载荷Claims claims = getClaimsFromToken(token);// 通过载荷获取到用户名userName = claims.getSubject();} catch (Exception e) {// 如果出现异常则将 userName 设置为空userName = null;}return userName;}/*** 从token中获取载荷** @param token token* @return token中的载荷*/private Claims getClaimsFromToken(String token) {Claims claims = null;try {claims = Jwts.parser()// 解密的秘钥.setSigningKey(secret).parseClaimsJws(token).getBody();} catch (Exception e) {e.printStackTrace();}return claims;}/*** 判断token是否可以被刷新** @param token token* @return token是否可以被刷新*/public boolean canRefresh(String token) {return !isTokenExpired(token);}/*** 判断token是否失效** @param token token* @return 当前token是否失效*/private boolean isTokenExpired(String token) {Date expiredDate = getExpiredDateFromToken(token);// 如果失效时间是在当前时间之前肯定是失效的return expiredDate.before(new Date());}/*** 获取token中的失效时间** @param token token* @return 当前token中的失效时间*/private Date getExpiredDateFromToken(String token) {// 从当前token中获取载荷Claims claims = getClaimsFromToken(token);// 从载荷中返回失效时间return claims.getExpiration();}/*** 刷新token** @param token 用户携带的 token* @return 刷新后的 token*/public String refreshToken(String token) {// 从当前token中获取载荷Claims claims = getClaimsFromToken(token);// 更新载荷中的失效时间改成当前时间claims.put(CLAIM_KEY_CREATED, new Date());// 重新生成tokenreturn generateToken(claims);}/*** 判断token是否有效** @param token 用户携带的 token* @param userDetails 载荷* @return token 是否有效*/public boolean validateToken(String token, UserDetails userDetails) {// 通过token是否已经过期、荷载中的用户属性与userDetails中的用户属性是否一致String userName = getUserNameFromToken(token);return userName.equals(userDetails.getUsername()) && !isTokenExpired(token);}
}
时间转化工具类
package com.trs.blog.util;import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;/*** 时间转化工具类** @author gaoziman* @date 2023/5/1 23:32*/
public class TimeUtil {/*** LocalDateTime 转 String** @param time LocalDateTime* @return 对应的字符串*/public static String localDateTimeToString(LocalDateTime time) {return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));}/*** 获取当前时间(字符串格式)** @return 当前时间*/public static String getNowTime(){SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return df.format(new Date());}/*** 获取当前时间(字符串格式)** @return 当前时间*/public static String getNowDate(){SimpleDateFormat df = new SimpleDateFormat("MM-dd");return df.format(new Date());}/*** String 转 LocalDate** @param time String* @return LocalDate*/public static LocalDate stringToLocalDateDay(String time){DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");return LocalDate.parse(time, df);}/*** String 转 LocalDate** @param time String* @return LocalDate*/public static LocalDate stringToLocalDate(String time){DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");return LocalDate.parse(time, df);}/*** String 转 LocalDateTime** @param time String* @return LocalDateTime*/public static LocalDateTime stringToLocalDateTimeDay(String time){// 先转LocalDate ===> 再转LocalDateTimeLocalDate localDate = stringToLocalDateDay(time);return localDate.atTime(LocalTime.now());}/*** String转LocalDateTime (yyyy-MM-dd HH:mm:ss格式)** @param time String格式时间* @return LocalDateTime*/public static LocalDateTime stringToLocalDateTime(String time){// 先转LocalDate ===> 再转LocalDateTimeLocalDate localDate = stringToLocalDate(time);return localDate.atTime(LocalTime.now());}/*** LocalDate转String** @param time LocalDate* @return String*/public static String localDateToString(LocalDate time) {return time.format(DateTimeFormatter.ofPattern("MM-dd"));}}
UUID生成工具类
package com.trs.blog.util;import java.util.UUID;/*** UUID生成工具类** @author gaoziman* @date 2023/5/1 23:32*/
public class UuidUtil {public static String[] chars = new String[]{"a", "b", "c", "d", "e", "f","g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s","t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I","J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V","W", "X", "Y", "Z"};/*** 获取短UUID** @return 16位UUID*/public static String getShortUuid() {StringBuffer shortBuffer = new StringBuffer();String uuid = UuidUtil.getUuid();for (int i = 0; i < 8; i++) {String str = uuid.substring(i * 4, i * 4 + 4);int x = Integer.parseInt(str, 16);// 对62取余shortBuffer.append(chars[x % 0x3E]);}return shortBuffer.toString();}/*** 获得32位UUID*/public static String getUuid() {String uuid = UUID.randomUUID().toString();//去掉“-”符号return uuid.replaceAll("-", "");}}
MD5工具类
package com.trs.common.util;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public final class MD5 {public static String encrypt(String strSrc) {try {char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f' };byte[] bytes = strSrc.getBytes();MessageDigest md = MessageDigest.getInstance("MD5");md.update(bytes);bytes = md.digest();int j = bytes.length;char[] chars = new char[j * 2];int k = 0;for (int i = 0; i < bytes.length; i++) {byte b = bytes[i];chars[k++] = hexChars[b >>> 4 & 0xf];chars[k++] = hexChars[b & 0xf];}return new String(chars);} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new RuntimeException("MD5加密出错!!+" + e);}}public static void main(String[] args) {System.out.println(MD5.encrypt("123456"));}
}
7.knife4j文档
引入依赖
<!--knife4j-->
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
package com.trs.serviceUtil.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;import java.util.ArrayList;
import java.util.List;/*** knife4j配置信息*/
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfig {@Beanpublic Docket adminApiConfig(){List<Parameter> pars = new ArrayList<>();ParameterBuilder tokenPar = new ParameterBuilder();tokenPar.name("token").description("用户token").defaultValue("").modelRef(new ModelRef("string")).parameterType("header").required(false).build();pars.add(tokenPar.build());//添加head参数endDocket adminApi = new Docket(DocumentationType.SWAGGER_2).groupName("adminApi").apiInfo(adminApiInfo()).select()//只显示admin路径下的页面.apis(RequestHandlerSelectors.basePackage("com.trs")).paths(PathSelectors.regex("/.*")).build().globalOperationParameters(pars);return adminApi;}private ApiInfo adminApiInfo(){return new ApiInfoBuilder().title("后台管理系统-API文档").description("本文档描述了个人博客后台管理系统接口定义").version("1.0").contact(new Contact("manman", "http://manamn.space", "2942894660@qq.com")).build();}}
8.文件上传
导入依赖
<!-- 阿里云OSS文件上传开始 --><!-- 阿里云 OSS --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.14.1</version></dependency><!--日期时间工具--><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>2.10.14</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><!-- 阿里云OSS文件上传结束 -->
#阿里云文件上传
aliyun:oss:endpoint: ************keyid: ************keysecret: ************bucketname: ************
配置类读取配置文件
package com.trs.demo.oss;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** oss属性*/
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssProperties {private String endPoint;private String keyId;private String keySecret;private String bucketName;
}
Controller
package com.trs.demo.controller;import com.trs.demo.service.FileService;
import com.trs.demo.util.Result;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;@RestController
@RequestMapping("/oss/file")
public class OSSController {@Resourceprivate FileService fileService;/*** 文件上传** @param file* @param module* @return*/@PostMapping("/upload")public Result upload(MultipartFile file, String module) {//返回上传到oss的路径String url = fileService.upload(file, module);return Result.ok(url).message("文件上传成功");}
}
Service
package com.trs.demo.service.impl;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.trs.demo.oss.OssProperties;
import com.trs.demo.service.FileService;
import org.apache.commons.io.FilenameUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;/*** @author : gaoziman* @description :* @date 2023/5/8 9:47*/
@Service
public class FileServiceImpl implements FileService {/*** oss属性*/@Resourceprivate OssProperties ossProperties;/*** 文件上传** @param file 文件上传对象* @param module 文件夹名称* @return {@link String}*/@Overridepublic String upload(MultipartFile file, String module) {//获取地域节点String endPoint = ossProperties.getEndPoint();//获取AccessKeyIdString keyId = ossProperties.getKeyId();//获取AccessKeySecretString keySecret = ossProperties.getKeySecret();//获取BucketNameString bucketName = ossProperties.getBucketName();try {//创建OSSClient实例OSS ossClient = new OSSClientBuilder().build(endPoint, keyId,keySecret);//上传文件流InputStream inputStream = file.getInputStream();//获取旧名称String originalFilename = file.getOriginalFilename();//获取文件后缀名String extension = FilenameUtils.getExtension(originalFilename);//将文件名重命名String newFileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;//使用当前日期进行分类管理String datePath = new DateTime().toString("yyyy/MM/dd");//构建文件名newFileName = module + "/" + datePath + "/" + newFileName;//调用OSS文件上传的方法ossClient.putObject(bucketName, newFileName, inputStream);//关闭OSSClientossClient.shutdown();//返回文件地址return "https://" + bucketName + "." + endPoint + "/" + newFileName;} catch (IOException e) {e.printStackTrace();}return null;}/*** 删除文件** @param url url*/@Overridepublic void deleteFile(String url) {//获取地域节点String endPoint = ossProperties.getEndPoint();//获取AccessKeyIdString keyId = ossProperties.getKeyId();//获取AccessKeySecretString keySecret = ossProperties.getKeySecret();//获取BucketNameString bucketName = ossProperties.getBucketName();try {//创建OSSClient实例OSS ossClient = new OSSClientBuilder().build(endPoint, keyId, keySecret);//组装文件地址String host = "https://" + bucketName + "." + endPoint + "/";//获取文件名称String objectName = url.substring(host.length());//删除文件ossClient.deleteObject(bucketName, objectName);} catch (Exception e) {e.printStackTrace();}}
}
相关文章:

SpirngBoot + Vue 前后端分离开发工具代码
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Java从入门到精通 ✨特色专栏…...

【数据结构初阶】单链表(附全部码源)
单链表 1,单链表的概念及结构2,单链表的实现2.1初始化内容(所需文件,接口)2.2申请结点2.3打印单链表2.4尾插2.5头插2.6尾删2.7头删2.8查找2.9在pos位置之后插入2.10在pos位置前面插入2.11删除pos之后的值2.12删除pos位…...

数据治理入门
处理模式 模式名称常见场景常见框架批处理夜间几个小时,无人值守hive spark datax流处理7*24H一直运行,无人值守maxwell, flink, flume, kafka即席处理人机交互接口访问 web页面 数据治理的意义 数据质量低:数据错误,不准确或不…...

uniapp 微信小程序登录 新手专用 引入即可
预览 第一步导入插件 在引入的页面的登录按钮下拷贝一下代码 <template><view class"content"><button type"primary" click"login">微信登录</button></view><TC-WXlogin :wxloginwxlogin /> </templ…...

PMCW体制雷达系列文章(4) – PMCW雷达之抗干扰
说明 本文作为PMCW体制雷达系列文章之一,主要聊聊FMCW&PMCW两种体制雷达的干扰问题。事实上不管是通信领域还是雷达领域,对于一切以电磁波作为媒介的信息传递活动,干扰是无处不在的。近年来,随着雷达装车率的提高,…...

Gin框架源码解析
概要 目录 Gin路由详解 Gin框架路由之Radix Tree 一、路由树节点 二、请求方法树 三、路由注册以及匹配 中间件含义 Gin框架中的中间件 主要讲述Gin框架路由和中间件的详细解释。本文章将从Radix树(基数树或者压缩前缀树)、请求处理、路由方法树…...

MacOS设置JAVA_HOME环境变量
首先先查看一下,系统当前使用的java是谁,可以使用/usr/libexec/java_home命令 % /usr/libexec/java_home /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home检查一下这个路径下的文件,发现这是一个jre的目录。加上-V参数看…...
闭眼检测实现
引言 这段代码是一个实时眼睛状态监测程序,可以用于监测摄像头捕获的人脸图像中的眼睛状态,判断眼睛是否闭合。具体应用实现作用说明如下: 1. 实时监测眼睛状态 通过摄像头捕获的实时视频流,检测人脸关键点并计算眼睛的 EAR&a…...

系列六、Java垃圾回收器主要有哪些?
一、Java垃圾回收器主要有哪些? UseSerialGC、UseParallelGC、UseConcMarkSweepGC、UseParallelNewGC、UseParallelOldGC、UseG1GC...

【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis
目录 【7】Spring Boot 3 集成组件:缓存组件 spring cache spring data redis什么是缓存抽象声明式注解JSR-107对应SpEL上下文数据 引入依赖cache 支持的缓存类型缓存类型配置NONESIMPLEREDIS自定义配置 CAFFEINE Hazelcast...总结 个人主页: 【⭐️个人主页】 需要…...

说说Java中的不可重入锁
什么是锁? 简单来讲在Java中,锁是一种用于并发控制的机制,用于保护共享资源,防止多个线程同时访问或修改数据导致的数据不一致性和线程安全问题。在Java虚拟机(JVM)中,每个对象都有一个相关联的…...

C++学习 --vector
目录 1, 什么是vector 2, 创建vector 2-1, 标准数据类型 2-2, 自定义数据类型 2-3, 其他创建方式 3, 操作vector 3-1, 赋值 3-2, 添加元素 3-2-1, 添加元素(assi…...
Android图片涂鸦,Kotlin(1)
Android图片涂鸦,Kotlin(1) import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.graphics.PointF import android.…...

upload-labs(1-17关攻略详解)
upload-labs pass-1 上传一个php文件,发现不行 但是这回显是个前端显示,直接禁用js然后上传 f12禁用 再次上传,成功 右键打开该图像 即为位置,使用蚁剑连接 连接成功 pass-2 源码 $is_upload false; $msg null; if (isse…...

《 机器人基础 》期末试卷(A)
一、填空题(30分,每空2分) 1. 按照相机的工作方式,机器人常用相机分为1)__ 单目摄像头 2)__ 双目摄像头 _ 3)_深度摄像头_ 三类。 2. 度量地图强调…...

Azure Machine Learning - Azure AI 搜索中的矢量搜索
矢量搜索是一种信息检索方法,它使用内容的数字表示形式来执行搜索方案。 由于内容是数字而不是纯文本,因此搜索引擎会匹配与查询最相似的矢量,而不需要匹配确切的字词。本文简要介绍了 Azure AI 搜索中的矢量支持。 其中还解释了与其他 Azure…...

3 redis实现一个消息中间件
使用list实现一个队列,可以从左侧入队,也可以从右侧入对 即可以从左侧读取,也可以从右侧读取 1、Lindex Lindex 命令用于通过索引获取列表中的元素 也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的…...

js添加dom到指定div之后,并给添加的dom类名,然后设置其样式,以及el-popover层级z-index过高问题解决。
遇到一个需求,Vue项目做一个表格,要求表头与表格内容分开,如下效果所示,表头与表格有个高度间隔边距(箭头所示),因为默认我们的el-table的表头与内容是一起的: 思路:通过querySelector获取el-table__header-wrapper元素,通过createElement创建一个div,通过 newElem…...

C语言结构体
#include <stdio.h> #include <string.h> #include <stdlib.h>//struct Student_s { // int num; // char name[20]; // char gender; // int age; // float Chinese; // float Math; // float English; // char addr[30]; //}; //最后的分号一定要写&#x…...

【Python大数据笔记_day10_Hive调优及Hadoop进阶】
hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时,不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率,或帮助定位问…...

React经典初级错误
文章 前言错误场景问题分析解决方案后言 前言 ✨✨ 他们是天生勇敢的开发者,我们创造bug,传播bug,毫不留情地消灭bug,在这个过程中我们创造了很多bug以供娱乐。 前端bug这里是博主总结的一些前端的bug以及解决方案,感兴…...

C# System.Array.CopyTo() 和 System.Array.Clone() 有什么区别
System.Array.CopyTo() 和 System.Array.Clone() 是用于数组复制的两种不同方法,它们在实现和用途上有一些区别。 System.Array.CopyTo() 方法: CopyTo() 方法用于将数组的元素复制到另一个数组。它是 Array 类的实例方法,可以用于复制一个…...

Stable Diffusion 启动时 got an unexpected keyword argument ‘socket_options‘ 错误解决
Stable Diffusion 启动时 got an unexpected keyword argument socket_options 错误解决 问题解决方法 问题 Launching Web UI with arguments: Traceback (most recent call last):File "launch.py", line 48, in <module>main()File "launch.py"…...

CSS 文本属性篇
文字颜色 属性名:color作用:控制文字的颜色可选值: 1.颜色名 color: blue; 2.rgb或rgba color:rgb(132, 220, 254); color:rgba(132, 220, 254,0.5); 3.hex或hexa(十六进制) color:#0078d4; color:#0078d48b; 4.hsl或h…...
Activiti,Apache camel,Netflex conductor对比,业务选型
Activiti,Apache camel,Netflex conductor对比,业务选型 1.activiti是审批流,主要应用于人->系统交互,典型应用场景:请假,离职等审批 详情可见【精选】activti实际使用_activiti通过事件监听器实现的优势_记录点滴…...

pythom导出mysql指定binlog文件
要求 要求本地有py环境和全局环境变量 先测试直接执行binlog命令执行命令 Windows 本地直接执行命令 # E:\output>E:\phpstudy_pro\Extensions\MySQL5.7.26\bin\mysqlbinlog binglog文件地址 # --no-defaults 不限制编码 # -h mysql链接地址 # -u mysql 链接名称 # -p m…...

TDengine 跨版本迁移实战
TDengine 3.0 已经退出了近一年,目前已经到了 3.2 版本。很遗憾的是 2.x 和 3.x 之间的数据文件不兼容。 如果向从 2.x 升级到 3.x 只能选择数据迁移的方式。 目前数据迁移有三种方法: 使用官方推荐工具 taosx。使用 taosdump 工具。自己写程序。 迁移…...

FPGA设计时序约束八、others类约束之Set_Case_Analysis
目录 一、序言 二、Set Case Analysis 2.1 基本概念 2.2 设置界面 2.3 命令语法 2.4 命令示例 三、工程示例 四、参考资料 一、序言 在Vivado的时序约束窗口中,存在一类特殊的约束,划分在others目录下,可用于设置忽略或修改默认的时序…...

xftp连接wsl2
在WSL中默认是没有安装OpenSSH,需要自己安装。 安装 sudo apt update sudo apt install openssh-server检查是否安装成功 ssh -V配置ssh sudo vim /etc/ssh/ssh_config设置端口 Port 22启动ssh服务 sudo service ssh startxftp连接 主机地址:127.…...

Cross-View Transformers for Real-Time Map-View Semantic Segmentation 论文阅读
论文链接 Cross-View Transformers for Real-Time Map-View Semantic Segmentation 0. Abstract 提出了 Cross-View Transformers ,一种基于注意力的高效模型,用于来自多个摄像机的地图视图语义分割使用相机感知的跨视图注意机制隐式学习从单个相机视…...