Java [后端] 开发日常记录(1)
目录
1、常用的注解
2、对字符串的处理
3、对JSON串的处理
-- The End --
详细如下:
1、常用的注解
- 若返回的字段中有NUll,则不返回
- @JsonInclude(value = JsonInclude.Include.NON_NULL)
//在实体类中添加这个注解
@JsonInclude(JsonInclude.Include.NON_NULL)
- @RequestBody
常用来接收处理application/json
、application/xml
等类型的数据 contentType 为 application/json类型
@RestController = @Controller + @ResponseBody
- @requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),
它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 通过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。
- @Synchronized
@synchronized 可以解决接口简单的并发,使用的时候只需要放在对应并发的接口或者代码块前面即可。 @synchronized 所处理的问题与锁(递归锁NSRecursiveLock)类似;可以防止不同的线程同时执行同一段代码。@synchronized 用着更方便,可读性更高, 自然效率会比较低。
递归锁: 同一个线程可以重复的加锁而不会导致死锁(互斥锁: 同一个线程重复加锁会导致死锁) ,加的递归锁全部执行完后 才会把资源让给别的线程。
@synchronized 递归锁详解_想名真难的博客-CSDN博客_递归锁原理
锁主要存在四种状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁。但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。
- @JsonFormat()
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")可以格式化时间,接口可以返回格式化后的时间。如:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
推荐使用:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
- 后端数据校验(当然前端校验可能会更方便一些,可以前端校验的话,可以使用前端校验)
Validator + BindResult进行数据校验
Validator可以非常方便的制定校验规则,在实体类里需要校验的字段加上注解,每个注解对应不同的校验规则。
如:在实体类中的name添加
@ NotNull(message = "用户名不能为空")
@ Size(min = 6, max = 11, message = "用户名长度必须是6-16个字符")
private String username;
然后在接口中添加 注解@Valid
/**
* 用户新增
*/
@PostMapping("/add")
public String addUser(@RequestBody @Valid UserInfo userInfo, BindingResult bindingResult) {
// 如果有参数校验失败,会将错误信息封装成对象组装在BindingResult里
for (ObjectError error : bindingResult.getAllErrors()) {
return error.getDefaultMessage();
}
return userInfoService.insertUserInfo(userInfo);
}
//当然也可以这样,就会直接把异常返给前端了
@PostMapping("/add")
public String addUser(@RequestBody @Valid UserInfo userInfo) {
return userInfoService.insertUserInfo(userInfo);
}
校验的结果就会返回到BindingResult中,有错误信息就直接返回给前端了。
当然前端校验也可能会方便一些,前端vue中数据校验如下,在form中添加:rules="rules",然后在中定义即可:
: rules = "rules"
// 表单校验
data() {
return {
rules: {
phone: [{
required: true,
message: "联系电话不能为空",
trigger: "blur"
}, {
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
],
}
}
@PathVariable
@PathVariable 映射 URL 绑定的占位符;带占位符的 URL 是 Spring3.0 新增的,通过 URL 中的 {xxxx} 占位符可以通过@PathVariable(“xxxx“) 绑定到操作方法的入参中。
具体实例如下:
@PostMapping("/login/{name}/{pwd}")
@ResponseBody
public String loginTest(@PathVariable("name")String name, @PathVariable("pwd")String pwd){
System.out.println("name = " + name);
System.out.println("pwd = " + pwd);
return "Success";
}
@DeleteMapping("/del/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
System.out.println("ids = " + ids);
return toAjax(deleteDataService.deleteDatainfoByIds(ids));
}
@RequestHeader
获取发送请求地址的头部信息如:一些浏览器信息
Accept 浏览器可接受的MIME类型
Accept-Charset 浏览器支持的字符编码
Accept-Encoding 浏览器知道如何解码的数据编码类型(如 gzip)。Servlets 可以预先检查浏览器是否支持gzip并可以对支持gzip的浏览器返回gzipped的HTML页面,并设置Content-Encoding回应头(response header)来指出发送的内容是已经gzipped的。在大多数情况下,这样做可以加快网页下载的速度。
Accept-Language 浏览器指定的语言,当Server支持多语种时起作用。
Authorization 认证信息,一般是对服务器发出的WWW-Authenticate头的回应。
Connection 是否使用持续连接。如果servlet发现这个字段的值是Keep-Alive,或者由发出请求的命令行发现浏览器支持 HTTP 1.1 (持续连接是它的默认选项),使用持续连接可以使保护很多小文件的页面的下载时间减少。
Content-Length (使用POST方法提交时,传递数据的字节数)
Cookie (很重要的一个Header,用来进行和Cookie有关的操作,详细的信息将在后面的教程中介绍)
Host (主机和端口)
If-Modified-Since (只返回比指定日期新的文档,如果没有,将会反回304 “Not Modified”)
Referer (URL)
User-Agent (客户端的类型,一般用来区分不同的浏览器)
如下:红框即为可通过@RequestHeader获取的内容
@RequestParam
是将请求URL的参数获取到;
具体如下:
请求 URL:
GET http://127.0.0.1:8081/applet/info?code=1234567890
@GetMapping("/applet/info")
public String loginTest(@RequestParam("code")String code){
System.out.println("code = " + code);
return "Success";
}
@RequestParam(value = "queryName", required = false) String queryName
不传值后台也不会报错,默认为null,但是int类型不能为null,解决办法,修改成Integer
@JsonIgnore 接口不返回指定的字段:
如:用户表查询的时候不返回密码等字段;
@JsonIgnore
private String password;
也可以这样的使用
//忽略,不返回预留字段一,预留字段二"resOne ", "resTwo"
@JsonIgnoreProperties(value = {"resOne", "resTwo"})
2、对字符串的处理
- 字符串的截取、拼接、替换
截取:具体可使用subString()方法来进行字符串截取、或使用StringUtils方法、或使用split()+正则表达式来进行截取字符串;
//===============substring()==================
String str = "zbcad123456";
int i;
public String Aa = str.substring( int beginIndex);
//该子字符串从指定索引处的字符开始,直到此字符串末尾;
str = str.substring(i);
//如:取第i个后面的字符
public String Ab = str.substring( int beginIndex, int endIndex);
//从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符,该子字符串的长度为 endIndex-beginIndex;
//参数说明:beginIndex – 起始索引(包括)、endIndex – 结束索引(不包括)。
//如:取字符串的前i个字符
str = str.substring(0, i);
//从右边开始取i个字符
str = str.substring(str.length() - i);
str = str.substring(str.length() - i, str.length());
//从右边开始去掉i个字符
str = str.substring(0, str.length() - i);
//从开始截取到中间某个指定字符 midChar (该字符出现的第一次)
str = str.substring(0, str.indexOf("1"));
System.out.println("str = " + str);
//从开始截取到指定某段字符串结尾 midStr
str = str.substring(0, str.indexOf("a") + "a".length());
System.out.println("str = " + str);
//=======StringUtils方法===================================================
//与str.subString()方法相同
String str1 = "abcdefgsad123456";
StringUtils.substring(str1, 2);
StringUtils.substring(str1, 2, 8);
//截取某个字符串之前的字符 ,第一个”d”开始
StringUtils.substringBefore(str1, "d");
//最后一个“d”开始
StringUtils.substringBeforeLast(str1, "d");
//截取某个字符串之后之前的字符
StringUtils.substringAfter(str1, "d");
StringUtils.substringAfterLast(str1, "d");
//截取两个字符串之间隔的字符
StringUtils.substringBetween(str1, "d");
//第一个字符“d”与第一个字符“1”之间的字符串
StringUtils.substringBetween(str1, "d", "1");
//第一个字符“d”与第一个字符“1”之间的字符串 结果是数组
StringUtils.substringsBetween(str1, "d", "1");
//======================split()=====================
//1. split() 主要是用于对一个字符串进行分割成多个字符串数组。标准形式为String[] strings = str.split("");
//2. split() 方法中括号中的参数可以为一个也可以为多个,每个参数之间用 | 隔开。并且每个参数之间要紧挨着 |。如:这里有三个参数:空格、逗号、问号:String[] strings = string.split(" |,|\\?");
//3. 像?.(点)((正括弧))(反括弧)*(星号)|(竖线)等特殊符号都要在其前面加上\\。
//4. str.split("");使用默认的情况下,split()方法对每个字符进行分割。
//split()和正则表达式
String str2 = "A,B,C,D,E";
String[] strs = str.split(",");
for (int i = 0, len = strs.length; i < len; i++) {
System.out.println(strs[i].toString());
}
拼接:直接使用“+”即可;
替换:直接使用 replace()或replaceAll() 即可;
- 使用NanoId生成ID
UUID和NanoID是开发中常用ID标识符之一;NanoId的特点:容量小、更安全、速度快、兼容性好、支持自定义字符、没有第三方依赖。
使用方法:
<!--导入 https://mvnrepository.com/artifact/com.aventrix.jnanoid/jnanoid -->
<dependency>
<groupId>com.aventrix.jnanoid</groupId>
<artifactId>jnanoid</artifactId>
<version>2.0.0</version>
<scope>runtime</scope>
</dependency>
添加工具类:
import java.security.SecureRandom;
import java.util.Random;
public final class NanoIdUtils {
public static final SecureRandom DEFAULT_NUMBER_GENERATOR = new SecureRandom();
public static final char[] DEFAULT_ALPHABET = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
public static final int DEFAULT_SIZE = 21;
private NanoIdUtils() {
}
public static String randomNanoId() {
return randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, 21);
}
public static String randomNanoId(Random random, char[] alphabet, int size) {
if (random == null) {
throw new IllegalArgumentException("random cannot be null.");
} else if (alphabet == null) {
throw new IllegalArgumentException("alphabet cannot be null.");
} else if (alphabet.length != 0 && alphabet.length < 256) {
if (size <= 0) {
throw new IllegalArgumentException("size must be greater than zero.");
} else {
int mask = (2 << (int)Math.floor(Math.log((double)(alphabet.length - 1)) / Math.log(2.0D))) - 1;
int step = (int)Math.ceil(1.6D * (double)mask * (double)size / (double)alphabet.length);
StringBuilder idBuilder = new StringBuilder();
while(true) {
byte[] bytes = new byte[step];
random.nextBytes(bytes);
for(int i = 0; i < step; ++i) {
int alphabetIndex = bytes[i] & mask;
if (alphabetIndex < alphabet.length) {
idBuilder.append(alphabet[alphabetIndex]);
if (idBuilder.length() == size) {
return idBuilder.toString();
}
}
}
}
}
} else {
throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols.");
}
}
}
3、对JSON串的处理
使用阿里巴巴的 fastjson 进行处理
//JSON字符串转换成JSON对象
JSONObject JscodeParaseObject = JSONObject.parseObject(jsCode);
String jscode = JscodeParaseObject.getString("jsCode");
这个就是可以拿到JSON串里面的值了。
解析json字符串内容(多层)
下面是实例:
{
"msg": "操作成功",
"code": 200,
"data": {
"ChannelCode": "001",
"Body": {
"dov": "000",
"doc": [
{
"id": "1",
"name": "java",
"url": "https://www.oracle.com/cn/java/technologies/downloads/",
"dept": {
"remark": "xxxx",
"params": {},
"orderNum": "xxxx",
"phone": "xxxx",
"children": []
}
},
{
"id": "2",
"name": "python",
"url": "https://www.python.org/downloads/"
},
{
"id": "3",
"name": "C",
"url": "http://c.biancheng.net/"
}
]
}
}
}
java 处理
//两个依赖包
//com.alibaba.fastjson2.JSONArray;
//com.alibaba.fastjson2.JSONObject;
String jsonString = "上面的Json串";
System.out.println("jsonString = " + jsonString);
JSONObject jsonObject = JSONObject.parseObject(jsonString);
//解析【第一层节点】 获取第一层的集合内容
String code = jsonObject.getString("code");
System.out.println("code = " + code);
//解析【第二层节点】 获取第二层的集合内容
JSONObject A0 = jsonObject.getJSONObject("data");
String ChannelCode = A0.getString("ChannelCode");
System.out.println("ChannelCode = " + ChannelCode);
//解析【第三层节点】 获取第三层的集合内容
JSONObject Ai = A0.getJSONObject("Body");
String dov = Ai.getString("dov");
System.out.println("dov = " + dov);
//解析【第四层节点】 获取第四层数组内容
JSONArray A1 = Ai.getJSONArray("doc");
//创建List nameList = [java, python, C]
List<String> nameList = new ArrayList<String>();
//对doc的数据进行循环,第四层数组中集合的内容
for (int i = 0; i < A1.size(); i++) {
JSONObject jsonObject1 = A1.getJSONObject(i);
String name = jsonObject1.getString("name");
System.out.println("name = " + name);
nameList.add(jsonObject1.getString("name"));
}
System.out.println("nameList = " + nameList);
4、Map和Json转换
1、Map => Json
有如下两个常用方法:
Map<String, Object> data = new HashMap<>();
data.put("userId", sqJhyNedis.getReceiver());
data.put("title", sqJhyNedis.getTitle());
data.put("content", sqJhyNedis.getContent());
System.out.println("data = " + data);
//将map集合中的数据转成json格式
//【方法一】使用net.sf.json.JSONObject包
JSONObject mapToJson1 = JSONObject.fromObject(data);
System.out.println("mapToJson1 = " + mapToJson1);
//【方法二】使用org.json.JSONObject包
JSONObject mapToJson2 =new JSONObject(data);
System.out.println("mapToJson2 = " + mapToJson2);
2、Json => Map
具体的方法如下:
//将json格式转成Map集合
String jsonStr="{\"releaseTime\":\"xxxxxxxxxx\",\"title\":\"xxxxxxxxxx\",\"userId\":\"xxxxxxxxxx\",\"content\":\"xxxxxxxxxx\"}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> mapData = new HashMap<>();
mapData =objectMapper.readValue(jsonStr, HashMap.class);
System.out.println("mapData = " + mapData);
//Map mapData1 =objectMapper.readValue(jsonStr, Map.class);
//System.out.println("mapData1 = " + mapData1);