Spring Boot从二到三

标签: Springboot 分类: Java 创建时间:2019-11-06 05:30:56 更新时间:2024-11-15 10:49:43

继续爬坑。

1.spring boot的@RequestBody获取前端传入的字符串

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping("uploadCoordinates")
public ApiResult uploadCoordinates(@RequestBody Inspection inspection){
try {
inspectionRep.save(inspection);
return new ApiResult(200,"位置上传成功");
}catch (Exception e){
logger.error("uploadCoordinates",e);
return new ApiResult(500,"位置上传失败");
}

}

本意是想将前端传入的json字符串,直接转换为inspection类。前端传入的json字符串如下:

结果还是报错:org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

经过测试,要想用requestbody,必须使用post方式,下面这样就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
url:this.urlConfig.uploadCoordinates,
contentType: "application/json; charset=utf-8",
dataType: "json",
type:"post",
data:inspectionObj,
success:function (data) {
console.log(data);
},
error:function (err) {
console.log(err);
}
})

另一个问题是,在请求时,出现了这么一个错误: Unrecognized token ‘id’: was expecting (‘true’, ‘false’ or ‘null’); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token ‘id’: was expecting (‘true’, ‘false’ or ‘null’)

解决方法是对要传递的对象数据进行 JSON.stringify(inspectionObj),这样在使用时就没有问题了。最后的ajax如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
url:this.urlConfig.uploadCoordinates,
contentType: "application/json; charset=utf-8",
dataType: "json",
type:"post",
data:JSON.stringify(inspectionObj),
success:function (data) {
console.log(data);
},
error:function (err) {
console.log(err);
}
})

2.SpringBoot命令行(CommandLineRunner初始化启动)

SpringBoot除了能开发web应用程序的功能外,还可以开放命令行工具,比如我想在应用程序启动的时候,就执行某些操作,但是直接在main函数中,调用某个bean的方法,会提示通过@Autowired自动注入的bean是一个空值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@SpringBootApplication
@MapperScan("com.bibichuan.bigdata.mapper")
@EnableScheduling
public class BigdataApplication {
@Autowired
private static ClickhouseImport clickhouseImport;

public static void main(String[] args) {
SpringApplication.run(BigdataApplication.class, args);

// 执行相关内容
String startdate="2016-09-20";
String enddate="2016-09-21";

clickhouseImport.getBetween();
clickhouseImport.getBetween(startdate,enddate);
}
}

这里的clickhouseImport就会是一个空。如果想实现在应用程序启动之后完成一些初始化工作,就需要实现CommandLineRunner接口,然后重写run方法。这样就既可以进行初始化,又可以使用SpringBoot提供的各种bean服务了,比如@Service等。当然也可以在main函数之外实现一个单独的@Component实现CommandLineRunner接口,SpringBoot依然可以实现初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@SpringBootApplication
@MapperScan("com.bibichuan.bigdata.mapper")
@EnableScheduling
public class BigdataApplication implements CommandLineRunner {

@Autowired
private ClickhouseImport clickhouseImport;

public static void main(String[] args) {
SpringApplication.run(BigdataApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
System.out.println("sldkjfslkdjf");
// 执行相关内容
String startdate="2016-09-20";
String enddate="2016-09-21";
clickhouseImport.getBetween(startdate,enddate);
}
}

3.读写Resource文件夹的文件

我想读取resource文件夹下的insert.sql文件

【尝试方法】
(1) 方法一:使用ResourceUtils类进行读取

但是使用”classpath:insert.sql”,出现了无法找到文件的问题

1
ResourceUtils.getFile("classpath:insert.sql");

(2) 方法二:直接将”classpath:insert.sql”作为参数传递个FileOutputStream,结果也没有引用到resource文件夹下的insert.sql文件,但是没有报错,结果不知道写到哪里去了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void fileAppend(String file, String conent) {
BufferedWriter out = null;

try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("classpath:insert.sql", true)));
out.write(conent);
} catch (Exception e) {
logger.error("fileAppend",e);
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
logger.error("fileAppend",e);
}
}
}

(3) 方法三:我也尝试了使用google的guava进行操作,但是就是无法获取resource文件夹下的文件。如下内容,使用getResource无法获取resources/test文件夹下的insert.sql文件,显示NotFound。

参考文章:
1.springboot读取resource下的文本文件 使用的是ResourceUtils这个类
2.Spring Boot 获取 java resources 下文件 有两种方式,第一种也是使用的ResourceUtils这个类,第二种使用的是ClassPathResource
3.Guava(Resources用法) 读取 classpath 中的文件、读取HTTP 这里提到了借助Guava库的Resource类进行文件的读写
5.java读取resource目录下文件的方法示例 和上面的一样,也是使用了Guava的Resource类
6.java中outputStream与inputStream的相互转换
7.Java – Write an InputStream to a File
8.Java读取resource文件/路径的几种方式
9.java读取resource目录下的文件
10.getResource方法路径参数的不同

(4) 方法四:最后还是没有解决读取到的target\classes文件下的文件而不是resources文件夹的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
    * 追加文件:使用FileOutputStream,在构造FileOutputStream时,把第二个参数设为true
    *
    * @param fileName
    * @param content
    */
public static void fileAppend(String filepath, String conent) {
BufferedWriter out = null;
try {
URL fileUrl=Resources.getResource("sql/"+filepath);
File file=new File(fileUrl.getFile());
if(file!=null){
System.out.println(file.getAbsolutePath());
}
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
out.write(conent);

} catch (Exception e) {
logger.error("fileAppend",e);
} finally {
try {
if(out!=null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
logger.error("fileAppend",e);
}
}
}

【解决方法】
使用SpringBoot的ClassPathResource,读取resource目录下的inp/pipeline.inp,注意引用的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ClassPathResource classPathResource = new ClassPathResource(inpFilePath+"pipeline.inp");
// 这种方式是错误的
// File inpFile = new File(classPathResource.getPath());
try {
File inpFile = classPathResource.getFile(); // 这是正确的方法
BufferedReader bufferedReader = new BufferedReader(new FileReader(inpFile));
StringBuilder content = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
content.append(line);
System.out.println(line);
}
}catch (Exception e){
logger.error("文件读取失败",e);
}
参考文章:
1.SpringBoot读取Resource下文件的几种方式 第一种:ClassPathResource加上classPathResource.getInputStream();第二种:Thread.currentThread().getContextClassLoader().getResourceAsStream;第三种:this.getClass().getResourceAsStream;第四种:ResourceUtils.getFile。前三种方法在开发环境(IDE中)和生产环境(linux部署成jar包)都可以读取到,第四种只有开发环境 时可以读取到,生产环境读取失败。这几个方法在其他的文章中也看到过。
2.Java 按行读取文件
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。