SpringBoot
系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、IDEA 插件
这里只是推荐一下好用的插件,具体的使用方法不一一详细介绍。
JRebel for IntelliJ
一款热部署插件,只要不是修改了项目的配置文件,用它都可以实现热部署。收费的,破解比较麻烦。不过功能确实很强大。算是开发必备神器了。热部署快捷键是control+F9/command+F9。
.ignore
git提交时过滤掉不需要提交的文件,很方便,有些本地文件是不需要提交到Git上的。
CamelCase
将不是驼峰格式的名称,快速转成驼峰格式,安装好后,选中要修改的名称,按快捷键shift+alt+u。
Lombok plugin
开发神器,可以简化你的实体类,让你i不再写get/set方法,还能快速的实现builder模式,以及链式调用方法,总之就是为了简化实体类而生的插件。
Mybatis plugin
可以在mapper接口中和mapper的xml文件中来回跳转,就想接口跳到实现类那样简单。
codehelper.generator
可以让你在创建一个对象并赋值的时候,快速的生成代码,不需要一个一个属性的向里面set,根据new关键字,自动生成掉用set方法的代码,还可以一键填入默认值。
GenAllSetter 特性
在Java方法中, 根据 new 关键词, 为Java Bean 生成所有Setter方法。
按GenAllSetter键两次, 会为Setter方法生成默认值。
可在Intellij Idea中为GenAllSetter设置快捷键。
如何使用:
将光标移动到 new 语句的下一行。
点击主菜单Tools-> Codehelper-> GenAllSetter, 或者按下GenAllSetter快捷键。
GenDaoCode 特性
根据Pojo 文件一键生成 Dao,Service,Xml,Sql文件。
Pojo文件更新后一键更新对应的Sql和mybatis xml文件。
提供insert,insertList,update,select,delete五种方法。
能够批量生成多个Pojo的对应的文件。
自动将pojo的注释添加到对应的Sql文件的注释中。
丰富的配置,如果没有配置文件,则会使用默认配置。
可以在Intellij Idea中快捷键配置中配置快捷键。
目前支持MySQL + Java,后续会支持更多的DB。
如果喜欢我们的插件,非常感谢您的分享。
GenDaoCode 使用方法
主菜单Tools-> Codehelper-> GenDaoCode 按键便可生成代码。
方法一:点击GenDaoCode,然后根据提示框输入Pojo名字,多个Pojo以 | 分隔。
Codehelper Generator会根据默认配置为您生成代码。
方法二:在工程目录下添加文件名为codehelper.properties的文件。
点击GenDaoCode,Codehelper Generator会根据您的配置文件为您生成代码。
GsonFormat
一键根据json文本生成java类,非常方便
GenerateAllSetter
一键调用一个对象的所有set方法并且赋予默认值 在对象字段多的时候非常方便,在做项目时,每层都有各自的实体对象需要相互转换,但是考虑BeanUtil.copyProperties()等这些工具的弊端,有些地方就需要手动的赋值时,有这个插件就会很方便,创建完对象后在变量名上面按Alt+Enter就会出来 generate all setter选项。
CodeGlance
在编辑区的右侧显示的代码地图。
下面几个是装X神器了(让你的开发工具变得靓丽起来)
Material Theme UI
这是一款主题插件,可以让你的ide的图标变漂亮,配色搭配的很到位,还可以切换不同的颜色,甚至可以自定义颜色。默认的配色就很漂亮了,如果需要修改配色,可以在工具栏中Tools->Material Theme然后修改配色等。
Background image Plus
这是一款可以设置idea背景图片的插件,不但可以设置固体的图片,还可以设置一段时间后随机变化背景图片,以及设置图片的透明度等等。
active-power-mode
这是一款让你在编码的时候,整个屏幕都为之颤抖的插件。
Nyan progress bar
这是一个将你idea中的所有的进度条都变成萌新动画的小插件。
Rainbow Brackets
彩虹颜色的括号 看着很舒服 敲代码效率变高
Mybatis Log Plugin
Mybatis现在是java中操作数据库的首选,在开发的时候,我们都会把Mybatis的脚本直接输出在console中,
MyBatis Log Plugin 这款插件是直接将Mybatis执行的sql脚本显示出来,无需处理,可以直接复制出来执行的 。
二、注解
·springboot 注解的一些 使用
1. Springboot中Bigdecimal以json格式返回前端丢失小数点
@JsonFormat(shape = JsonFormat.Shape.STRING)
@NotNull(message="价格不能为空!")
@Column(precision = 10, scale = 2)
private BigDecimal price;
2. 注解 @CrossOrigin 解决跨域问题
出于安全原因,浏览器禁止Ajax调用驻留在当前原点之外的资源。例如,当你在一个标签中检查你的银行账户时,你可以在另一个选项卡上拥有EVILL网站。来自EVILL的脚本不能够对你的银行API做出Ajax请求(从你的帐户中取出钱!)使用您的凭据。
跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFRAME或JSONP。
在Controller 类上添加此注解 @CrossOrigin 表示为整个类启用。如下只启用一个接口为例:
/**
* 联系我们 添加
*/
@Log(title = "联系我们 添加", businessType = BusinessType.UPDATE)
@CrossOrigin(allowCredentials = "true",allowedHeaders = "*")
@PostMapping("/setContactUs")
@ResponseBody
public AjaxResult setContactUs(SysContactUs sysContactUs)
{
return toAjax(sysContactUsService.insertSysContactUs(sysContactUs));
}
三、Springboot中emoji表情配置及springboot数据源配置区别
springboot mysql 中默认不支持插入emoji表情,
首先确定mysql数据库本身是否支持emoji : mysql配置emoji
然后:DataSource中增加初始化sql配置: set names utf8mb4
首先确定自己使用的springboot整合的数据源是哪种( 有springboot自带的tomcat-jdbc数据源, 也可以使用druid数据源)
1.tomcat-jdbc数据源:
参考源码:tomcat-jdbc_DataSource设置
application.properties中增加:
spring.datasource.initSQL=set names utf8mb4
例如:
#连接池配置(tomcat-jdbc数据源)
spring.datasource.initSQL=set names utf8mb4
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800
2. druid数据源
连接池配置(pom引入:druid ,新增@Configuration: com.*.*.*.DruidConfig)
application.properties中增加:
spring.datasource.connectionInitSqls=set names utf8mb4
例如:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-on-return=false
spring.datasource.test-while-idle=true
spring.datasource.pool-prepared-statements=true
spring.datasource.maxActive=20
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,log4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.connectionInitSqls=set names utf8mb4
3. 移动端传过来的表情直接过滤掉(方法)
/**
* 过滤表情
* @param source
* @return
*/
public static String filterEmoji(String source) {
if(source != null)
{
Pattern emoji = Pattern.compile ("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]|[\ue000-\uf8ff]",Pattern.UNICODE_CASE | Pattern . CASE_INSENSITIVE ) ;
Matcher emojiMatcher = emoji.matcher(source);
if ( emojiMatcher.find())
{
source = emojiMatcher.replaceAll("");
return source;
}
return source;
}
return source;
}
四、工具类
1. 使用Dozer优雅的将DO转换成VO
使用Dozer优雅的将DO转换成VO
在Web开发中,我们会接触到很多领域模型中的概念,其中大部分和实体相关的概念都有缩写,一般以O(Object)结尾。其中比较常见的由DO、DTO、VO、DAO等。我们也经常有把一个实体对象转换为另外一个实体对象的操作。本文主要是介绍一种作者在实践中总结的一种自认为比较优雅的转换方式。欢迎拍砖。
什么是DO、DTO和VO
在Java中 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念中介绍过Java中的各种模型概念。 在这里简单再总结一下:
在日常的项目开发中,VO对应于页面上需要显示的数据(表单),DO对应于数据库中存储的数据(数据表),DTO对应于除二者之外需要进行传递的数据。
很多人可能对VO和DTO并不是那么熟悉,相反对DO却比较熟悉,那是因为在很多项目中由于种种原因我们只使用了DO,原因可能有以下几种:
1、项目太小,对于一种业务实体,封装成一个DO就够了。
2、并不熟悉DTO、VO,更不知道他们之间的区别。
3、了解DO\DTO\VO之间的区别,但是懒得用。
添加 pom.xml 包
<!-- JavaBean映射工具库 -->
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
创建工具类接口 BeanMappingHandler
package com.hzks.common.mapper;
public interface BeanMappingHandler<S, T> {
T map(S source, Class<T> destinationClass);
}
创建工具类 BeanMapper
package com.hzks.common.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
public class BeanMapper {
/**
* 持有Dozer单例, 避免重复创建DozerMapper消耗资源.
*/
private static DozerBeanMapper dozer = new DozerBeanMapper();
/**
* 基于Dozer转换对象的类型.
*/
public static <T> T map(Object source, Class<T> destinationClass) {
return dozer.map(source, destinationClass);
}
/**
* 基于Dozer转换Collection中对象的类型.
*/
public static <T> List<T> mapList(List<?> sourceList, Class<T> destinationClass) {
List<T> destinationList = Lists.newArrayList();
if (sourceList == null) {
return new ArrayList<>();
}
sourceList.forEach(source -> {
T destinationObject = dozer.map(source, destinationClass);
destinationList.add(destinationObject);
});
return destinationList;
}
public static <S, T> T map(S source, Class<T> destinationClass, BeanMappingHandler<S, T> handler) {
return handler.map(source, destinationClass);
}
/**
* 基于Dozer转换Collection中对象的类型.
*/
public static <S, T> List<T> mapList(List<S> sourceList, Class<T> destinationClass, BeanMappingHandler<S, T> handler) {
List<T> destinationList = Lists.newArrayList();
for (S sourceObject : sourceList) {
T destinationObject = handler.map(sourceObject, destinationClass);
destinationList.add(destinationObject);
}
return destinationList;
}
public static <T> Page<T> mapPage(Page sourcePage, Class<T> destinationClass) {
List<T> destinationList = Lists.newArrayList();
for (Object sourceObject : sourcePage.getRecords()) {
T destinationObject = dozer.map(sourceObject, destinationClass);
destinationList.add(destinationObject);
}
Page<T> pageData = new Page<>();
BeanUtils.copyProperties(sourcePage, pageData, "records");
pageData.setRecords(destinationList);
return pageData;
}
public static <S, T> Page<T> mapPage(Page<S> sourcePage, Class<T> destinationClass,
BeanMappingHandler<S, T> handler) {
List<T> destinationList = Lists.newArrayList();
for (S sourceObject : sourcePage.getRecords()) {
T destinationObject = handler.map(sourceObject, destinationClass);
destinationList.add(destinationObject);
}
Page<T> pageData = new Page<>();
BeanUtils.copyProperties(sourcePage, pageData, "records");
pageData.setRecords(destinationList);
return pageData;
}
/**
* 基于Dozer将对象A的值拷贝到对象B中.
*/
public static void copy(Object source, Object destinationObject) {
dozer.map(source, destinationObject);
}
}
添加操作 Controller
@Api(tags="后台用户管理",value = "后台用户管理")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping("/api/admin/user")
@RestController
public class SysUserController extends BaseController {
private final ISysUserService sysUserService;
@ApiOperation(value = "个人信息修改", notes = "个人信息修改")
@PostMapping("/setSysUserUpdate")
public ResultUtil setSysUserUpdate(@ApiIgnore SysUserDto sysUser) throws IOException {
sysUser.setUserId(thisUser.getUserId());
SysUser s= BeanMapper.map(sysUser,SysUser.class);
// Dozer转换对象类型.
ResultUtil r= ResultUtil.toResult(sysUserService.updateUserInfo(s));
if (!r.isSuccess()){
return r;
}
return ResultUtil.ok(sysUser);
}
}
2. 判断对象为空 (所有属性是否为空)
/**
* 判断对象是否为空,且对象的所有属性都为空
* ps: boolean类型会有默认值false 判断结果不会为null 会影响判断结果
* 序列化的默认值也会影响判断结果
* @param object 对象
* @return Boolean
*/
@SuppressWarnings("rawtypes")
public static boolean objCheckIsNull(Object object) {
// 得到类对象
Class clazz = (Class) object.getClass();
// 得到所有属性
Field fields[] = clazz.getDeclaredFields();
// 定义返回结果,默认为true
boolean flag = true;
for (Field field : fields) {
field.setAccessible(true);
Object fieldValue = null;
try {
// 得到属性值
fieldValue = field.get(object);
// 得到属性类型
Type fieldType = field.getGenericType();
// 得到属性名
String fieldName = field.getName();
/// System.out.println("属性类型:" + fieldType + ",属性名:" + fieldName + ",属性值:" + fieldValue);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
if (fieldValue != null) {
// 只要有一个属性值不为null 就返回false 表示对象不为null
flag = false;
break;
}
}
return flag;
}
public void getBinding(String requestJson) {
// json 转对象
SccUserMember sccUserMember = JSON.toJavaObject(JSONObject.parseObject(requestJson),SccUserMember.class);
sccUserMember.setDeptId(thisUser.getDeptId());
//判断字符串是否为空
if (!org.springframework.util.StringUtils.StringUtils.isEmpty(sccUserMember.getAdvisorId())){
// 操作....
}
SccUserMember member=sccUserMemberService.get(sccUserMember.getId());
//判断对象是否为空
if (!org.springframework.util.StringUtils.StringUtils.isEmpty(member)){
// 操作....
}
List<SysCourseToAuditDto> list=sysVipCourseService.get();
//判断对象是否为空
if (cn.hutool.core.collection.CollUtil.CollUtil.isNotEmpty(list)) {
// 操作....
}
}
3. JSON (转换)
1. 字符串转 集合对象
方式(1)
@PostMapping("/updateNode")
public ResponseEntity<JsonResult> updateNode(@RequestBody String params){
List<Node> nodes = JSON.parseArray(params, Node.class);
JsonResult r = new JsonResult();
try {
processService.updateNode(nodes);
r.setMsg("ok");
} catch (Exception e) {
r.setObj(e.getClass().getName() + ":" + e.getMessage());
r.setMsg("error");
e.printStackTrace();
}
return ResponseEntity.ok(r);
}
方式(2)
Gson gson = new Gson();
List<Person> persons = new ArrayList<Person>();
for (int i = 0; i < 10; i++) {
Person p = new Person();
p.setName("name" + i);
p.setAge(i * 5);
persons.add(p);
}
String str = gson.toJson(persons); // 转字符串
Person person = gson.fromJson(str, Person.class); // 转换 单一实体
List<Person> ps = gson.fromJson(str, new TypeToken<List<Person>>(){}.getType()); // 转换成list
总结
提示:这里对文章进行总结:…