文章目录
- Java程序猿搬砖笔记(六)
- @RequestBody注解支持空参数
- windows查看占用端口并杀死对应进程
- MySQL和MyBatis对JSON类型字段的处理
- Java连接8.0版本的MySQL
- Spring整合Activiti测试时报错
- Apache CXF客服端调用失败
- IDEA几个常用快捷键
- jps -l命令
- IDEA配置svn
- IDEA更新svn项目提示authentication required解决方法
- 引入Swagger后前端访问路径默认加了/v2/api-docs
- Java实体转Map
- mybatis做动态排序的时候,字段打印出字符串解决方法
- SpringBoot接收对象属性的属性时为空
- Spring中的@Transactional(rollbackFor = Exception.class)属性详解
- 用了lombok的@Data注解就不要继承关系
- 如何理解 public static T
- Java BigDecimal累加
- 利用BeanMap进行对象与Map的相互转换
- 使用reflect反射对象与Map的相互转换
- Linux 脚本 sh 和 ./ 的区别
- git分支相关操作命令
- SpringBoot 定义全局日期响应格式
- SpringBoot对多模块包扫描问题
- Spring的@RequestBody注解接收参数时如果实体类属性以if和k开头,那么传参会接收不到
- mysql bigint类型和datetime类型的转换
- 使用EasyExcel导入问题
- 校验导入的Excel数据是否重复
Java程序猿搬砖笔记(六)
作为码农平时搜集一些小知识点个人认为是个不错的习惯,书上说
好记性不如烂笔头
我想即使是以前忽略或者新get的很简单的东西,自己动手记下来不管如何印象也会更深刻。
@RequestBody注解支持空参数
@RequestBody(required=false),get/post且实体不加无参构造方法都行
windows查看占用端口并杀死对应进程
E:\Documents\MyIdeaProjects\act\target>netstat -ano |findstr "8888"
TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING 14176
TCP [::]:8888 [::]:0 LISTENING 14176
E:\Documents\MyIdeaProjects\act\target>tasklist |findstr "14176"
javaw.exe 14176 Console 2 254,736 K
E:\Documents\MyIdeaProjects\act\target>taskkill /f /t /im "javaw.exe"
成功: 已终止 PID 14176 (属于 PID 13304 子进程)的进程。
E:\Documents\MyIdeaProjects\act\target>netstat -ano |findstr "8888"
MySQL和MyBatis对JSON类型字段的处理
-
MySQL有JSON字段,MyBatis不支持JSON类型字段的处理,需要自己写Handler
-
MySQL存有转义字符的JSON会报错,比如"apiParam":"{orderId:" o r d e r I d orderId orderId"}"
Java连接8.0版本的MySQL
Java连接的8.0版MySQL时需要把mysql-connector-java包换成8.X版本的,把链接换成com.mysql.cj.jdbc.Driver。com.mysql.cj.jdbc.Driver是6.x版本的新功能,需要指定时区serverTimezone和useSSL报com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server错误同样是因为数据库版本太高了而对应的驱动器太低了。相关代码如下:
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!-- dbcp链接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///activiti_demo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
Spring整合Activiti测试时报错
错误如下:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngine': FactoryBean threw exception on object creation; nested exception is org.apache.ibatis.exceptions.PersistenceException:
Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'activiti_spring.act_ge_property' doesn't exist
原因:因为mysql使用schema标识库名而不是catalog,因此mysql会扫描所有的库来找表,如果其他库中有相同名称的表,activiti就以为找到了,本质上这个表在当前数据库中并不存在。设置nullCatalogMeansCurrent=true,表示mysql默认当前数据库操作,在mysql-connector-java 5.xxx该参数默认为true,在6.xxx以上默认为false,因此需要设置nullCatalogMeansCurrent=true。
解决方法:配置mysql连接时加上:nullCatalogMeansCurrent=true。
代码如下:
<property name="url" value="jdbc:mysql://localhost:3306/activiti_spring?nullCatalogMeansCurrent=true"/>
Apache CXF客服端调用失败
错误信息如下:
Caused by: org.apache.cxf.binding.soap.SoapFault: Unexpected wrapper element
解决方法:
- 客户端接口头部的@WebService加上服务端的命名空间(可以通过wsdl文档查看)
比如@WebService(targetNamespace=“http://service.ws.myapp.com/”) - 客户端和服务端包名改成一致的(不推荐)
IDEA几个常用快捷键
ctrl+home 跳到文件头
ctrl+end 跳到文件尾
ctrl+f1+1 定位到文件位置
ctrl+shift+u 大小写转换
jps -l命令
jps -l命令可以查看本地启动的java进程,这是Jdk提供的命令
IDEA配置svn
- 需要按照SVN的时候选择命令行,否则在svn客户端安装路径bin目录下找不到svn.exe。
- 重新安装SVN后,右键->settings(设置)->icon overlays(图标覆盖)->选择shell(windows外壳),如果无效需要修改注册表后重启。
参考链接
参考链接
IDEA更新svn项目提示authentication required解决方法
- File->Settings->Version Control->Subversion->Clear Auth Cache 这个时候IDEA拉取代码会报No appropriate protocol (protocol is disabled or cipher suites are inappropriate)错,需要进行第二步
- 本地拉取代码,提示框选择永久接受证书;再回到IDEA 成功拉取代码。
引入Swagger后前端访问路径默认加了/v2/api-docs
方法一、把属性文件的server.servlet.context-path=/portal去掉可以正常访问
方法二、
- 在资源目录新建一个属性文件,内容如下:
pringfox.documentation.swagger.v2.path=/
- 在SwaggerConfig配置类添加注解
@PropertySource("classpath:swagger.properties")
Java实体转Map
- Web项目推荐使用
BeanMap map = BeanMap.create(noticePageReq);
- Java项目推荐使用反射
mybatis做动态排序的时候,字段打印出字符串解决方法
<select id="queryNoticePageList" resultMap="BaseResultMap" parameterType="Map" >
select
<include refid="Base_Column_List" />
from t_notice
<if test="prop != null" >
order by #{prop}
<if test="order != null" >
#{order}
</if>
</if>
</select>
order by中打印出了字符串,在sql中会语法错误 :
select id, notice_type_id, title, source, description, status, create_time, update_time, create_user, last_update_user, is_show, release_time
FROM t_notice order by 'title' 'asc';
解决方法:
把上面的#{prop}改为${prop},#{order}改为${order}
SpringBoot接收对象属性的属性时为空
Java实体对象如下:
@Data
public class PageRequest<T>{
private Integer page; //当前页
private Integer rows; //每页显示数
private String prop; //排序字段名
private String order; //排序方式:asc或desc
private T data;
}
public class NoticePageReq {
@ApiModelProperty(value="公告标题")
private String title;
}
请求接口后:
解决方法1:在类NoticePageReq上添加@Data注解,这个注解会给属性加Set和get方法,需要添加lombok依赖。
解决方法2:在属性title添加@JsonProperty注解。这个注解的主要作用是把传过来的JSON值转换名称,比如下划线转驼峰,然后注入值。
Spring中的@Transactional(rollbackFor = Exception.class)属性详解
用了lombok的@Data注解就不要继承关系
如何理解 public static T
这是泛型方法。在方法中出现了泛型的结构,泛型参数与类的泛型参数无关。泛型方法所属的类是不是泛型类都可以。泛型方法可以声明为static。参考代码如下:
public class ValidatorUtil {
// 获取validator对象
private static Validator validator = Validation.byProvider(HibernateValidator.class).configure()
.failFast(false).buildValidatorFactory().getValidator();
public static <T> Set<ConstraintViolation<T>> validateBean(T bean){
Set<ConstraintViolation<T>> validateResult = validator.validate(bean);
return validateResult;
}
Java BigDecimal累加
BigDecimal awardMoney = new BigDecimal(0);
for(ImportDoubleAwardsField field: entrySet.getValue()){
awardMoney = awardMoney.add(field.getMoney());
}
注意BigDecimal的add()方法返回的是相加后的数据
利用BeanMap进行对象与Map的相互转换
不过项目中使用BeanMap.create()方法个别地方会报异常,可能是用了热部署工具dev-tools,但是我去掉这个也报错,索性改为了反射方法
参考链接
使用reflect反射对象与Map的相互转换
package edu.hrbeu.platform.modeling.common.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
/**
* 使用reflect进行转换
*/
public class MapTransformUtils1 {
public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) throws Exception {
if (map == null)
return null;
T obj = beanClass.newInstance();
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
continue;
}
field.setAccessible(true);
field.set(obj, map.get(field.getName()));
}
return obj;
}
public static Map<String, Object> objectToMap(Object obj) throws Exception {
if (obj == null) {
return null;
}
Map<String, Object> map = new HashMap<String, Object>();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
}
Linux 脚本 sh 和 ./ 的区别
git分支相关操作命令
查看当前分支
git branch
查看所有分支(本地和远程)
git branch -a
查看所有分支(远程)
git branch -r
切换分支
git checkout 分支名
创建分支
git branch 分支名
删除分支
删除前需要先切换到其他分支,然后执行下面的命令
git branch -D 分支名
合并master分支代码到dev
先切换到dev分支然后执行git merge master
SpringBoot 定义全局日期响应格式
方法一(消息转换器):
/**
* 设置全局响应日期格式
*
* @author liquanhong
* @createTime 2021/09/07
*/
@Configuration
public class Json2MessageConventerConfig {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
objectMapper.setDateFormat(sdf);
converter.setObjectMapper(objectMapper);
return converter;
}
}
这种方法如果前端传递接口未定义的参数会报JSON参数转换错误:
JSON parse error: Unrecognized field \"a\" (class com.aspirecn.rewardportal.common.entity.PageRequest), not marked as ignorable; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field \"a\" (class com.aspirecn.rewardportal.common.entity.PageRequest), not marked as ignorable (5 known properties: \"rows\", \"data\", \"prop\", \"order\", \"page\"])\n at [Source: (PushbackInputStream); line: 4, column: 9] (through reference chain: com.aspirecn.rewardportal.common.entity.PageRequest[\"a\"])
方法二(配置文件 推荐):
#在application.properties文件中配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#在application.yml文件中配置
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
方法三(在指定的Bean属性中添加注解):
@JsonFormat(timezone = "GMT+8", pattern = "yyyyMMddHHmmss")
private Date createTime;
需要有下面的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
注意如果有用到Fastjson ,注解可能会失效可以用@JSONField注解解决。
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updatedDate;
方法四(用于解决配置文件不生效的问题)
/**
* WebMvc配置
*
* @author liquanhong
* @createTime 2021/10/25
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 使用此方法, 以下 spring-boot: jackson时间格式化 配置 将会失效
* spring.jackson.time-zone=GMT+8
* spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
* 原因: 会覆盖 @EnableAutoConfiguration 关于 WebMvcAutoConfiguration 的配置
* */
@Override
public void extendMessageConverters(List converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = converter.getObjectMapper();
// 生成JSON时,将所有Long转换成String
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
// 时间格式化
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 设置格式化内容
converter.setObjectMapper(objectMapper);
converters.add(0, converter);
}
}
SpringBoot对多模块包扫描问题
方法一:
@SpringBootApplication(scanBasePackages = {"com.xx.xx.xx.A", "com.xx.xx.B"})
方法二:
https://blog.csdn.net/lintiyan/article/details/94362640
方法三(SpringBoot默认会扫描本模块下面的包):
@SpringBootApplication
@ComponentScan("com.xx.xx.B")
SpringBoot包扫描排除指定类
@ComponentScan(basePackages={"com.aspirecn.core.common","com.aspirecn.kjcgkyg"},
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = DruidConfig.class))
Spring的@RequestBody注解接收参数时如果实体类属性以if和k开头,那么传参会接收不到
前端入参:
{
"kBB": "kBB123",
"isBB": "isBB123",
"ifBB": "ifBB123"
}
后端接收不到,如下图所示:
isBB可以接收到。 接收ifBB、kBB需要在实体类的属性中加上注解。,如下面的代码所示:
@JsonProperty(value = "kBB")
private String kBB;
@JsonProperty(value = "ifBB")
private String ifBB;
mysql bigint类型和datetime类型的转换
1、bigint类型转换为datetime类型
select from_unixtime(1164691264437/1000);
2、datetime类型转换为bigint类型
select UNIX_TIMESTAMP('2021-09-13 11:24:59');
使用EasyExcel导入问题
- 如果在注解中添加index属性,value的名称可以和Excel的列名不一样;
- 如果没有添加index属性,value的名称必须和Excel的列名一样
@ExcelProperty(value = "研发能力类型名称",index = 6)
private String capabilityTypeName;
校验导入的Excel数据是否重复
比如要求同一类型成果同一年份同一成果名称不能相同,如下图所示:
1、先去数据库查询类型、年份和成果名拼接字符串列表得到List recordList
SELECT concat(type,'@',which_year,'@',name)
FROM t_achievement
WHERE type not in(1,2)
2、循环读到的Excel行,每读一条拼取一个key去recordList中匹配,然后把该条数据也放到recordList
String productKey = achievementDto.getType()+AchievementConstant.SEPARATOR_A+achievementDto.getWhichYear()+AchievementConstant.SEPARATOR_A+achievementDto.getName();
if(recordList.contains(productKey)){
errorBuilder.append(AchievementConstant.PRODUCT_NAME_REPEAT);
}
recordList.add(productKey);
这样把填写和数据库查询的数据都放到了一起,好处是不用再去单独校验用户填写的数据相互之间是否有问题。