# Object
Object类是所有类的父类,所有的类都直接或者间接的继承自Object类,一个类如果没有父类,默认继承自Object类
- toString()方法:返回对象的字符串表示,默认是由类的全路径+'@'+哈希值的十六进制表示。这个表示其实是没有意义的,一般子类都会重写该方法,例如String类,Integer类等等
- equals() 方法:比较两个对象是否相同。默认情况下,比较的是地址值是否相同。而比较地址值是没有意义的,所以,一般子类也会重写该方法
//使用 Objects.equals 方法判断两个值是否相等时,一定要保证两个入参的类型要一致
Integer a = 1;
long b = 1L;
System.out.println(Objects.equals(a,b));
//结果:false
//如果直接用包装类的 equals 方法,有个问题就是可能存在报空指针异常的风险
String e = null;
String f = "abc";
System.out.println(e.equals(f));
//结果:NullPointerException
# System
System.exit(int status) //终止当前的java虚拟机,非零表示异常终止
System.currentTimeMillis() //返回当前的时间(毫秒为单位)
new Scanner(System.in) //System.in代表输入
System.out.println() //System.out代表输出
System.arraycopy(srcArray,0,descArray,0,srcArray.length) //复制的方法
System.gc() //运行垃圾回收器
# 基本类型包装类
# Integer类
//构造函数
public Integer(int value)
public Integer(String s) //注意:s必须得是数字字符
//常用方法
public static Integer valueOf(int i) //返回int值的Integer实例
//注意:根据String值创建Interger对象,String值只能是数字
public static Integer valueOf(String s) //返回字符串值的Integer实例
public static String toBinaryString(int i):返回二进制
public static String toOctalString(int i):返回八进制
public static String toHexString(int i):返回16进制
//重写的toString方法,返回radix进制
public static String toString(int i,int radix):进制最大为36进制。因为数字加字母总数为36
int和String的相互转换
public static String valueOf(int i):String转int。该方法是String类中的方法
public static int parseInt(String s):int转String。该方法是Integer类中的方法
# Charactor类
Character类是char类型的包装类,它是对一个字符类型的变量进行操作。其实可以看成是对字符进行操作的一个工具类。
//构造方法:构造一个新分配的Character对象,代表指定的char值。
public Character(char value)
//常用方法
public static boolean isDigit():判断是否是数字
public static boolean isLetter():判断是否是字母
public static boolean isUpperCase()/isLowerCase():判断是否是大写/小写
public static boolean isWhiteSpace():判断是否为空格
public static char toUpperCase()/toLowerCase():转大写/小写
public static String toString():返回字符的字符串形式,字符串的长度仅为1
# BigInteger类
BigInteger:可以让超过Integer范围内的数据进行运算
//构造方法
public BigInteger(String val)
//常用方法
public BigInteger add(BigInteger val):加
public BigInteger subtract(BigInteger val):减
public BigInteger multiply(BigInteger val):乘
public BigInteger divide(BigInteger val):除
public BigInteger[] divideAndRemainder(BigInteger val):返回商和余数的数组
# BigDecimal类
由于在运算的时候,float类型和double很容易丢失精度。所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal。 BigDecimal类:不可变的、任意精度的有符号十进制数,可以解决数据丢失问题。
//构造方法
public BigDecimal(String val)
//成员方法
public BigDecimal add(BigDecimal augend) 加
public BigDecimal subtract(BigDecimal subtrahend) 减
public BigDecimal multiply(BigDecimal multiplicand) 乘
public BigDecimal divide(BigDecimal divisor) 除
public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode):商,几位小数
# 字符串 String
# String
String类在java.lang包下,所以使用的时候不需要导包
通过new创建字符串对象,每次new都会申请一个栈内存空间,即使内容相同,地址也不会相同
new String():创建一个空白字符串对象,不含有任何内容
new String(char[] chs):根据字符数组的内容,来创建字符串对象
new String(byte[] bys):根据字节数组的内容,来创建字符串对象
new String("abc"):直接赋值的方式
s1.equals(s2):比较字符串s1和s2是否相等(区分大小写)
s1.equalsIgnoreCase(s2):比较字符串s1和s2是否相等(不区分大小写)
s1.contains(s2):判断是否包含字符串s2
s1.startsWith(s2):判断字符串是否以字符串s2开头
s1.endsWith(s2):判断字符串是否以字符串s2结尾
s1.isEmpty():判断字符串是否为空
char charAt(int index):获取索引值为index的字符
int indexOf(int ch):返回指定字符在该字符串里出现的第一次位置的索引
int indexOf(String str):返回指定符串在该字符串里出现的第一次位置的索引
int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引
int indexOf(String str,int fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引
String subString(int start) 从指定位置开始截取字符串,默认到末尾。包含start这个索引
String subString(int start ,int end) 从指定位置开始到指定位置结束截取字符串。左包右不包
byte getBytes() 字符串转字节数组
char[] toCharArray() 字符串转字符数组
static valueof(……) 可以将任意类型的数据转换为字符串,经常用这个方法
String toLowerCase()/toUpperCase() 转小写/大写
String concat(String str) 与字符串str拼接
String replace(char old,char new) 把字符串中含有的所有的指定的字符替换为新的字符
String replace(String old,String new) 把字符串中含有的所有的指定的字符串 替换为新的字符串
String trim() 去除字符串两边的空格并返回
int compareTo(String str) 按字典返回两个字符串的大小
注意 split | (竖线)
在java中直接用split("|")是不行的,需要转义
String line = "866|10|1824261|214|";
String[] cells = line.split("\\|");
# StringBuilder
StringBuilder类在java.lang包下,是一个内容可变的字符串类
String对字符串进行拼接操作,每次拼接都会构建一个新的String对象,即耗时又浪费你内存
sb.reverse():返回相反的字符序列
# StringBuffer
StringBuilder类在java.lang包下,StringBuffer是线程安全的,所以在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些
String s = “abc”;
StringBuffer s1 = new StringBuffer(“123”);
StringBuffer s2 = new StringBuffer(s); //String转换为StringBuffer
String X = s1.toString(); //StringBuffer转换为String
//常用方法
StringBuffer append(boolean b):追加内容到当前StringBuffer对象的末尾
StringBuffer deleteCharAt(int index):删除指定位置的字符,然后将剩余的内容形成新的字符串
StringBuffer insert(int offset, boolean b):在StringBuffer对象中插入内容,然后形成新的字符串
StringBuffer reverse():将StringBuffer对象中的内容反转,然后形成新的字符串
void setCharAt(int index, char ch):修改对象中索引值为index位置的字符为新的字符ch
void trimToSize():将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费
void replace(int start,int end,String string):将StringBuffer对象中指定字符串进行替换
# 数组 Array
Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法
public static String toString(int[] a):返回指定数组的内容以字符串的形式表示
public static void sort(int[] a):按照数字顺序排列指定的数组
# 冒泡排序
一种排序方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直到所有的数据按要求完成排序
# split方法详解
# 单个分隔符
public class Test {
public static void main(String[] args) {
String str="2018,text,今天";
//单个分隔符用引号括起来即可
String[] data = str.split(",");
for(int i=0;i< data.length;i++){
System.out.println(data[i]);
//输出:2018 text 今天
}
}
}
- 对点进行处理
@Test
public void test0001(){
String str = "asczscx.xsa";
String[] split = str.split("[.]");
for (String s : split){
System.out.println(s);
}
}
- 对竖进行处理
public class Test {
public static void main(String[] args) {
String str="a|bc|8";
//java中\\表示一个普通\,\+特殊字符表示字符本身
String[] data = str.split("\\|");
for(int i=0;i< data.length;i++){
System.out.println(data[i]);
//输出:a bc 8
}
}
}
- 对星号进行处理
@Test
public void test0001(){
String str = "asczscx*xsa";
String[] split = str.split("\\*");
for (String s : split){
System.out.println(s);
}
}
- 对斜线进行处理
@Test
public void test0001(){
String str = "asczscx\\xsa";
String[] split = str.split("\\\\");
for (String s : split){
System.out.println(s);
}
}
- 对中括号的进行处理
@Test
public void test0001(){
String str = "asczscx[]xsa";
String[] split = str.split("\\[\\]");
for (String s : split){
System.out.println(s);
}
}
# 多个分隔符
public class Test {
public static void main(String[] args) {
String str="2021年11月18日;英语,数学,语文;";
//多个分隔符用引号括起来,并且用“|”进行分割
String[] data = str.split(",|;");
for(int i=0;i< data.length;i++){
System.out.println(data[i]);
//输出:2021年11月18日 英语 数学 语文
}
}
}
# 数据输出 print
System.out.println("输出内容带换行");
System.out.print("输出内容不带换行");
System.out.print();//起到换行的作用
# 数据输入Scanner
主要用于获取键盘输入的内容,在java.util包下
# 构造方法
Scanner sc = new Scanner(System.in);
# 基本方法
- hasNext():判断是否有值输入
- hasNextXxx():判断输入的值是否为Xxx型的
- nextXxx():用于返回键盘输入的Xxx类型的值。该方法可以使用多次
int i = sc.nextInt();
# next()和nextLine()方法的区别
- nextLine()方法仅仅是以Enter键为结束符,返回的是Enter键前面的所有字符,包括空格、Tab键等等
- next()方法结束符比nextLine()多,Enter键、空格、Tab键都是结束符。不过只有在输入有效字符之后,next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。即如果一开始就输入空格键、Tab键或Enter键,它是被无视
- 简单的说,就是next()方法无法获取带有空格、Tab键的字符串,而nextLine()方法则可以
# 随机数Random
- 导包:
import java.util.Random;
- 创建对象:
Random r = new Random();
- 接收数据:
int num = r.nextInt(10);
大于等于0小于10的数
public int nextInt():返回整型范围内的随机数
public int nextInt(int n):返回0到n范围内的随机数
//获取一个1-100之间的随机数
int x = r.nextInt(100)+1;
# 数字运算Math
没有构造方法,类的成员都是静态的,可以直接通过类名调用
public static int abs(int a):返回参数的绝对值
public static double ceil(double a):向上取整
public static double floor(double a):向下取整
public static int round(float a):四舍五入
public static int max(int a,int b):比较取较大值
public static int min(int a,int b):比较取较小值
public static double pow(double a,double b):返回a的b次幂
public static double random():返回[0.0-1.0]的值,不包含1.0
# 日期 Date
//构造方法
public Date() //根据当前的默认毫秒值创建对象
public Date(long date) //根据给定的毫秒值创建对象
//常用方法
public long getTime() //获取时间,以毫秒为单位
public void setTime() //设置时间,以毫秒为单位
public class Demo_Date {
public static void main(String[] args) {
//美国人看的懂的时间 Tue Nov 12 15:46:02 CST 2019 CST东八区
System.out.println(new Date().toString());
//中国人看的懂的时间 2019-11-12 15:46:02
System.out.println(new Date().toLocaleString());
System.out.println(System.currentTimeMillis());//毫秒值
for (int i=0;i<=1000000;i++){}
Date d=new Date();
d.setTime(15735442L);
System.out.println(d.toLocaleString());//中国人看的懂得时间
System.out.println(new Date().getTime());//毫秒值
}
}
# Date与String类互相转换
DateFormat:可以进行日期和字符串的转换,但是由于是抽象类,所以使用具体子类SimpleDateFormat
//构造方法
SimpleDateFormat(String pattern) //pattern模式字符串中:年y 月M 日d 时H 分m 秒s
//常用方法
public final String format(Date date) //按照构造函数中的pattern解析日期为字符串
public Date parse(String s) //按照构造函数中的pattern解析字符串为日期
public class DateFormatDemo {
public static void main(String[] args) throws ParseException {
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = sdf.format(d);
System.out.println(s);
String str = "2010-10-10 10:10:10";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(str);
System.out.println(dd);
}
}
# 日历 Calendar
- Calendar提供了一个类方法getInstance()用于获取Calendar对象,其值已用当前日期和时间初始化
- 在使用Calendar获取月份的时候,要注意Calendar获取月份是从0开始的,所以要+1
Calendar rightNow = Calendar.getInstance();
//常用方法
//设置日历的年、月、日、时、分、秒。
public void set(int year,int month,int date,int hourofday,int minute,int second)
public int get(int field):返回给定日历字段的值。所谓字段就是年、月、日等等。
abstract void add(int field,int amount):按照日历的规则,给指定字段添加或减少时间量。
public long getTimeInMillies():以毫秒为单位返回该日历的时间值
public void setTime(Date date):使用给定的Date设置此日历的时间。Date=>Calendar
public Date getTime():返回一个Date表示此日历的时间。Calendar=>Date
public class CalendarDemo {
public static void main(String[] args) {
// 其日历字段已由当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance(); // 子类对象
// 获取年
int year = rightNow.get(Calendar.YEAR);
// 获取月 月份是从0开始的,所以要+1
int month = rightNow.get(Calendar.MONTH) + 1;
// 获取日
int date = rightNow.get(Calendar.DATE);
//获取几点
int hour=rightNow.get(Calendar.HOUR_OF_DAY);
//获取上午下午
int moa=rightNow.get(Calendar.AM_PM);
if(moa==1)
System.out.println("下午");
else
System.out.println("上午");
//给指定字段添加或减少时间量
rightNow.add(Calendar.YEAR,5);
rightNow.add(Calendar.DATE, -10);
}
}
# 读取properties
- 使用getClassLoader,该方式有局限但是如果配置文件在类路径(src)下比较方便
Properties properties = new Properties();
// 使用ClassLoader加载properties配置文件生成对应的输入流,默认路径是src下
ClassLoader classLoader = PropertiesTest.class.getClassLoader();
InputStream in = classLoader.getResourceAsStream("com/jay/ct/b.properties");
// 使用properties对象加载输入流
properties.load(in);
// 获取key对应的value值
String name = properties.getProperty("name");
注意
配置文件在当前类所在的包下,需使用包名限定:com/jay/ct/b.properties;配置文件在src根目录下,直接使用a.properties
- 基于 InputStream 读取配置文件,该方式的优点在于可以读取任意路径下的配置文件
Properties properties = new Properties();
// 使用InPutStream流读取properties文件
BufferedInputStream b2 = new BufferedInputStream(new FileInputStream("E:/b.properties"));
properties.load(b2);
// 获取key对应的value值
String name = properties.getProperty("name");
- 通过 java.util.ResourceBundle 类来读取,不需要加.properties后缀名,默认路径是src下
ResourceBundle resource = ResourceBundle.getBundle("a");
String name = resource.getString("name");
- ResourceUtils获取文件
File file = ResourceUtils.getFile("classpath:excelfile/03版.xls");
# 解析Json
# List转Json
使用Gson类中的toJson()方法
Gson gson = new Gson();
String listToJsonString = gson.toJson(list);
# 对象序列化/反序列化
Jackson是当前使用比较广泛的序列化和反序列化 json 开源框架,由三部分组成:
- jackson-core: 核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson内部实现正是通过高性能的流模式API的JsonGenerator 和 JsonParser 来生成和解析 json
- jackson-annotations: 注解包,提供标准注解功能
- jackson-databind: 数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API
Jackson提供了ObjectMapper来供程序员调用writeValue()序列化 或 调用readValue()反序列化方法之前,往往需要设置 ObjectMapper 的相关配置信息
# 忽略未知字段
默认情况下Jackson要求JSON字符串消息 和 Java类中的字段必须一一相对应,否则反序列解析JSON字符串时会报错。当然也可以通过配置Jackson的ObjectMapper属性使Jackson在反序列化时,忽略在 json字符串中存在但 Java 对象不存在的属性
//java对象属性
@Data
public class User implements Serializable {
private Integer age;
private String name;
}
//需要反序列化JSON字符串
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"age\":10,\"name\":\"曹操\",\"class\":\"语文\"}";
#会报错:因为json字符串的属性和java对象属性没有一一对应
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//异常
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "class"
//解决办法:忽略未知字段 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES默认是true。
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
# 属性为NULL不被序列化
如果java对象的属性为NULL则不参与序列化,即java对象序列化后的json串里不出现属性为null的字段。该功能可以使用@JsonInclude注解,也可以设置objectMapper属性
//java对象属性
@Data
public class User implements Serializable {
private Integer age;
private String name;
}
//序列化属性有为null的对象
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(10);
String string = objectMapper.writeValueAsString(user);
System.out.println(string);
}
//输出:json字段带null
{"age":10,"name":null}
//解决办法:
//1、注解可以加到类或属性上,加到类上表示多所有属性都有效
@JsonInclude(JsonInclude.Include.NON_NULL)
//2、设置objectMapper属性
objectMapper.setSerializationInclusion(Include.NON_NULL)
# 对象属性为空时,默认序列化会失败
默认情况下ObjectMapper序列化没有属性的空对象时会抛异常。可以通过SerializationFeature.FAIL_ON_EMPTY_BEANS设置当对象没有属性时,让其序列化能成功,不抛异常
//java对象属性:没有任何属性
@Data
public class User implements Serializable {
}
//默认序列化失败,会抛异常
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
#默认是true,空对象不让序列化
//objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
User user = new User();
String string = objectMapper.writeValueAsString(user); #会抛异常
System.out.println(string);
}
//抛异常:com.fasterxml.jackson.databind.exc.InvalidDefinitionException
//解决办法:关闭空对象不让序列化功能
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
# json字符串值带反斜杠(""),默认反序列化会失败
当反序列化的JSON串里带有反斜杠时,默认objectMapper反序列化会失败,抛出异常Unrecognized character escape。可以通过Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER来设置当反斜杠存在时,能被objectMapper反序列化
//java对象属性
@Data
public class User implements Serializable {
private Integer age;
private String name;
}
//反序列化字符串带反斜杠,会抛异常。
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
#objectMapper默认是false
objectMapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, false);
#name的值带反斜杠,默认情况下objectMapper解析器会反序列化失败
String json = "{\"age\":10,\"name\":\"曹\\操\"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:
//com.fasterxml.jackson.databind.JsonMappingException: Unrecognized character escape '操'
//解决办法:设置解析能识别JSON串里的注释符
objectMapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
# json字符串带注释符,默认反序列化会失败
当json字符串里带注释符时,默认情况下解析器不能解析。Feature.ALLOW_COMMENTS特性决定解析器是否允许解析使用Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)
//例如:如下反序列化JSON串里带注释,默认情况下objectMapper不能反序列化解析成对象
{
"age": 10
//,
//"name": "曹操"
}
//默认情况下,上面这种带注释的JSON串,objectMapper解析器是不能解析的
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//默认是false,不能解析带注释的JSON串
objectMapper.configure(Feature.ALLOW_COMMENTS, true);
String json = "{"
+"\"age\"" + ":" + 10 +
"/*" + "," +
"\"name\"" + ":" + "\"曹操\"*/" +
"}";
//Feature.ALLOW_COMMENTS打开时,JSON里的注释符会被过滤掉,解析器能解析
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:User(age=10, name=null)
# Json字符串里数字类型值为正无穷、负无穷或NaN时,默认反序列化会失败
objectMapper解析器默认不能识别识别 "Not-a-Number" (NaN)标识集合作为一个合法的浮点数 或 一个int数,objectMapper默认该功能是关闭的
//例如:反序列化的JSON串里包含了数字类型的属性值为NaN,默认objectMapper解析器是不能解析的
{
"age": NaN,
"name": "曹操"
}
//java对象属性:age是数字类型
@Data
public class User implements Serializable {
private Integer age;
private String name;
}
//数字类型 或 浮点类型值为NaN时,默认objectMapper解析器是不能解析的
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//需要开启Feature.ALLOW_NON_NUMERIC_NUMBERS
objectMapper.configure(Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
String json = "{\"age\":NaN, \"name\":\"曹操\"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
//输出是无穷大
System.out.println(0.0/0.0);
}
//输出:
User(age=NaN, name=曹操)
NaN
//注意:浮点类型 或 数字类型都可以接受NaN值,反序列化需要开启Feature.ALLOW_NON_NUMERIC_NUMBERS
# 反序列化可解析以"0"为开头的数字
默认情况下objectMapper解析器是不能解析以"0"为开头的数字,需要开启Feature.ALLOW_NUMERIC_LEADING_ZEROS才能使用
//例如java对象属性age是int类型
@Data
public class User implements Serializable {
private Integer age;
private String name;
}
//JSON字符串的age值是"0"为开头的数字,objectMapper默认是不能解析的
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
//“0”开头的数字
String json = "{\"age\":0012, \"name\":\"曹操\"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:User(age=12, name=曹操)
//注意:除了int类型,浮点数也一样
# Json反序列化可以解析单引号包住的属性名称和字符串值
parser解析器默认情况下不能识别单引号包住的属性和属性值,默认下该属性也是关闭的。需要设置JsonParser.Feature.ALLOW_SINGLE_QUOTES为true
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//需要开启单引号解析属性,默认是false
objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
String json = "{'age':12, 'name':'曹操'}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:如果Feature.ALLOW_SINGLE_QUOTES设置为false时,解析器会解析失败
User(age=12, name=曹操)
# 反序列Json字符串中包含制控制字符
Feature.ALLOW_UNQUOTED_CONTROL_CHARS该特性决定parser是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符\t、换行符\n和回车\r)。 如果该属性关闭,则如果遇到这些字符,则会抛出异常
//处理问题:JSON串里属性或属性值包含控制字符,解析器能解析。
{
"age": 12,
"name": "曹操\n"
}
//示列
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//开启单引号解析
objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
//开启JSON字符串包含非引号控制字符的解析(\n换行符)
objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
String json = "{'age':12, 'name':'曹操\n'}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:输出有换行效果
User(age=12, name=曹操)
# 反序列Json字符串中属性名没有双引号
默认情况下,标准的json串里属性名字都需要用双引号引起来。比如:{age:12, name:"曹操"}非标准的json串,解析器默认不能解析,需要设置Feature.ALLOW_UNQUOTED_FIELD_NAMES属性来处理这种没有双引号的json串
{
age: 12,
name: "曹操"
}
//示列
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
//开启单引号解析
objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
//开启属性名没有双引号的非标准json字符串
objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
String json = "{age:12, name:'曹操'}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
}
//输出:
User(age=12, name=曹操)
# 时间格式化
Jackson对时间(Date)序列化的转换格式默认是时间戳,可以取消时间的默认时间戳转化格式;默认时间戳转化格式取消后在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ,同时需要设置要展现的时间格式
//Jackson对时间(Date)序列化的转换格式默认是时间戳
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//WRITE_DATES_AS_TIMESTAMPS属性值默认就是true
//mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
String date = mapper.writeValueAsString(new Date());
System.out.println("默认是时间戳格式:" + date);
}
//输出:
//默认是时间戳格式:1605848842390
//取消时间的默认时间戳转化格式后,再序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//WRITE_DATES_AS_TIMESTAMPS属性值默认就是true
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
String date = mapper.writeValueAsString(new Date());
System.out.println("默认时格式:" + date);
}
//输出:
//默认时格式:"2020-11-20T05:12:22.868+0000"
//取消Jackson时间的默认时间戳转化格式,并设置需要展现的时间格式
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//取消时间的转化格式默认是时间戳,可以取消,同时需要设置要表现的时间格式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
String date = mapper.writeValueAsString(new Date());
System.out.println("指定时间时格式:" + date);
}
//输出:
//指定时间时格式:"2020-11-20 13:14:56"
Springboot使用的默认json解析框架是jackjson框架,在格式化Model时对Date属性指定时间格式方式有以下三种方法
//配置文件:将spring的jackson日期格式写在配置文件中即可。
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
write-dates-as-timestamps: false
//或者写成以下格式(主要取决于配置文件是什么格式的)
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.serialization.write-dates-as-timestamps=false
//注解:在实体Date类型的字段上使用@JsonFormat注解格式化日期
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT + 8")
private Date createTime;
//设置ObjectMapper属性:通过下面方式取消timestamps形式,并设置时间格式
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
# 解析XML
工具类,可以解析html或xml文档,返回Document,需要先导入jar包(jsoup-1.11.2.jar)
# parse解析html或xml文档
- parse(File in, String charsetName):解析xml或html文件的
- parse(String html):解析xml或html字符串
- parse(URL url, int timeoutMillis):通过网络路径获取指定的html或xml的文档对象
<?xml version='1.0'?>
<students>
<student id="1">
<name>Adair</name>
<age>18</age>
<gender>male</gender>
</student>
<student id="2">
<name>Mary</name>
<age>17</age>
<gender>female</gender>
</student>
</students>
//2.获取Document对象,根据xml文档获取
//2.1获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("./com/student.xml").getPath();
//2.2解析xml文档,加载文档进内存,获取dom树--->Document
Document document = Jsoup.parse(new File(path), "utf-8");
//3.获取元素对象 Element
Elements elements = document.getElementsByTag("name");
//elements是一个ArrayList
System.out.println("elements的元素个数:" + elements.size());
//3.1获取第一个name的Element对象
Element element = elements.get(0);
//3.2获取数据
String name = element.text();
System.out.println(name);
# 获取Element对象
- getElementById(String id):根据id属性值获取唯一的element对象
- getElementsByTag(String tagName):根据标签名称获取元素对象集合
- getElementsByAttribute(String key):根据属性名称获取元素对象集合
- getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
//1.获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("./com/student.xml").getPath();
//2.获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//3.获取元素对象
//3.1获取所有的student对象
Elements elements = document.getElementsByTag("student");
//3.2 获取属性名为id的元素对象们
Elements elements1 = document.getElementsByAttribute("id");
//3.3获取 number属性值为1的元素对象
Elements elements2 = document.getElementsByAttributeValue("number", "1");
//3.4获取id属性值的元素对象
Element it_cast1 = document.getElementById("it_cast1");
# 获取属性值及内容
- string attr(String key):根据属性名称获取属性值
- String text():获取文本内容
- String html():获取标签体的所有内容(包括字标签的字符串内容)
//1.获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("./com/student.xml").getPath();
//2.获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
Element element_student = document.getElementsByTag("student").get(0);
Elements element_name = element_student.getElementsByTag("name");
//获取student对象的属性值
String number = element_student.attr("number");
//获取文本内容
String text = element_name.text();
String html = element_name.html();
# selector选择器
- 使用的方法:Elements select(String cssQuery)
//1.获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("./com/student.xml").getPath();
//2.获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//3.查询name标签
Elements elements = document.select("name");
//4.查询id值为it_cast1的元素
Elements elements1 = document.select("#it_cast1");
//5.获取student标签并且number属性值为1的age子标签
//5.1.获取student标签并且number属性值为1
Elements elements2 = document.select("student[number='1']");
//5.2获取student标签并且number属性值为1的age子标签
Elements elements3 = document.select("student[number='1'] > age");
# XPath
- XPath即为XML路径语言,它是一种用来确定XML文档中某部分位置的语言
- 使用Jsoup的Xpath需要额外导入jar包
//1.获取student.xml的path
String path = JsoupDemo1.class.getClassLoader().getResource("./com/student.xml").getPath();
//2.获取Document对象
Document document = Jsoup.parse(new File(path), "utf-8");
//3.根据document对象,创建JXDocument对象
JXDocument jxDocument = new JXDocument(document);
//4.结合xpath语法查询
//4.1查询所有student标签
List<JXNode> jxNodes = jxDocument.selN("//student");
for(JXNode jxNode : jxNodes){
System.out.println(jxNode);
}
//4.2查询所有student标签下的name标签
List<JXNode> jxNodes1 = jxDocument.selN("//student/name");
for(JXNode jxNode : jxNodes1){
System.out.println(jxNode);
}
//4.3查询student标签下带有id属性的name标签
List<JXNode> jxNodes2 = jxDocument.selN("//student/name[@id]");
for (JXNode jxNode : jxNodes2){
System.out.println(jxNode);
}
//4.4查询student标签下带有id属性的name标签 并且id属性值为it_cast
List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id='it_cast1']");
for (JXNode jxNode : jxNodes3){
System.out.println(jxNode);
}
# 操作redis
# Jedis读写Redis数据
//导入坐标
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
//基本使用
public void testJedis() {
//1.连接Redis
Jedis jedis = new Jedis("127.0.0.1", 6379);
//空参时默认值为"127.0.0.1", 6379
//Jedis jedis = new Jedis();
//2.操作Redis
jedis.set("name", "lisi");
//3,关闭连接
jedis.close();
}
//操作String
public void testString() {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.set("name", "lisi");
String name = jedis.get("name");
jedis.setex("name", 20, "lisi"); //指定过期时间 20秒
jedis.close();
}
//操作Hash集合
public void testHash() {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.hset("hash", "a1", "b1");
jedis.hset("hash", "a2", "b2");
jedis.hset("hash", "a3", "b3");
jedis.hget("hash", "a1")
Map<String, String> hash = jedis.hgetAll("hash");
System.out.println(hash);
System.out.println(jedis.hlen("hash"));//获取哈希表中字段的数量
jedis.close();
}
//操作List集合
public void testList() {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.lpush("list", "a", "b", "c");//添加到表头
jedis.rpush("list", "x");//添加到表尾
List<String> list = jedis.lrange("list", 0, -1);//从表头取出
for (String s : list) {
System.out.println(s);
}
String element = jedis.lpop("list");
String element = jedis.rpop("list");
System.out.println(jedis.llen("list")); //获取列表长度
jedis.close();
}
//操作Set集合
public void testSet() {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.sadd("set", "java", "net"); //可以设置多个值
Set<String> set = jedis.smembers("set");
jedis.close();
}
//操作Sotedset集合
public void testSotedset() {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.zset("sotedset", 60, "a");
jedis.hset("sotedset", 50, "b");
Set<String> sotedset = jedis.zrange("sotedset", 0, -1);
jedis.close();
}
# Jedis连接池工具类
创建好工具类在使用中就可以不用每次都创建Jedis了,使用是直接调用工具类即可
#Redis连接地址
redis.host=127.0.0.1
#Redis连接ID
redis.port=6379
#最大链接数,设为0表示无限制
redis.maxTotal=30
#最大等待连接中的数量,设 0为没有限制
redis.maxIdle=10
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ResourceBundle;
public class RedisUtils {
//创建Redis连接池 JedisPool
private static JedisPool jp = null;
//创建Redis连接池配置
private static JedisPoolConfig jpc = null;
private static String host = null;
private static int port;
private static int maxTotal;
private static int maxIdle;
/**
* 静态代码块初始化资源
*/
static {
//读取配置文件参数值
ResourceBundle rb = ResourceBundle.getBundle("redis");
host = rb.getString("redis.host");
port = Integer.parseInt(rb.getString("redis.port"));
maxTotal = Integer.parseInt(rb.getString("redis.maxTotal"));
maxIdle = Integer.parseInt(rb.getString("redis.maxIdle"));
//连接池配置
jpc = new JedisPoolConfig();
jpc.setMaxTotal(maxTotal);
jpc.setMaxIdle(maxIdle);
//连接池
jp = new JedisPool(jpc, host, port);
}
/**
* 对外访问接口,提供Jedis连接对象,连接从连接池获取
*/
public static Jedis getJedis() {
return jp.getResource();
}
}
# BaseServlet
package cn.itcast.travel.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//不用加注解 因为Baseservlet根本不需要被访问到
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//System.out.println("baseServlet的service方法被执行了...");
//完成方法分发
//1.获取请求路径
String uri = req.getRequestURI(); // /travel/user/add
System.out.println("请求uri:" + uri);// /travel/user/add
//2.获取方法名称
String methodName = uri.substring(uri.lastIndexOf('/') + 1); /即获取add
System.out.println("方法名称:" + methodName);
//3.获取方法对象Method
//谁调用我?我代表谁
//UserServlet的对象cn.itcast.travel.web.servlet.UserServlet@4903d97e
System.out.println(this);
try {
//获取方法
Method method = this.getClass().getMethod(methodName,
HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
//暴力反射
//method.setAccessible(true);
method.invoke(this, req, resp);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
//要实现的功能的UserServlet
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
// 要用*号,要通配所有的方法名称
@WebServlet("/user/*") // /user/add /user/find
public class UserServlet extends BaseServlet {
//声明UserService业务对象
private UserService service = new UserServiceImpl();
//注册功能
public void regist(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//3.调用service完成注册
//UserService service = new UserServiceImpl();
boolean flag = service.regist(user);
ResultInfo info = new ResultInfo();
//4.响应结果
if(flag){
//注册成功
info.setFlag(true);
}else{
//注册失败
info.setFlag(false);
info.setErrorMsg("注册失败!");
}
//将info对象序列化为json
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(info);
//将json数据写回客户端
//设置content-type
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
}
}
# WebService
需要先安装WebService插件,setting -> pugins
# Apache Axis
Axis不支持Java8及以上的版本
- 创建普通Java项目
- 右键Add Framworks Support,选择WebService下的Apache Axis
- 配置Tomcat,测试项目是否启动成功
- 通过按两下shift,然后搜索webService,选择webService来打开窗口
- 修改Service URL,改成tomcat配置的访问地址
- 添加必要的jar包:Project Structure,如果报错,点击Fix->Add 'JAX-WS-Apache' to the…修复错误
- 访问WebService的时候;路径为:http://localhost:8080/flight/services
# 通过客户端调用服务端webservice
通过客户端调用服务端webservice (opens new window)
# 通过ajax调用WebService服务
通过ajax调用WebService服务 (opens new window)
# 下载远程文件并打包
String error = "错误图片";
String msg = "";
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
try {
//String downloadFilename = "图片.zip";// 文件的名称
//downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");// 转换中文否则可能会产生乱码
response.setContentType("application/octet-stream;charset=UTF-8");// 指明response的返回对象是文件流
//response.setHeader("Content-Disposition","attachment;filename="+downloadFilename);// 设置在下载框默认显示的文件名
for (String imgs : lImgs) {
msg = imgs;
//http://124.128.197.14:9300/statics/202337020004/202337020004-茎-20231018150456206.JPEG
//采集号+文件名
String imgFolderAndName = imgs.substring(imgs.indexOf("c")+3);
zos.putNextEntry(new ZipEntry(imgFolderAndName));
//文件名需要编码
String imgPath = imgs.substring(0,imgs.lastIndexOf("/")+1);
String imgName = imgs.substring(imgs.lastIndexOf("/")+1);
URL url = new URL(imgPath+ URLEncoder.encode(imgName,"UTF-8"));
// 打开连接
URLConnection con = url.openConnection();
//con.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko");
//设置请求超时为30s
con.setConnectTimeout(300*1000);
// 输入流
InputStream fis = con.getInputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
zos.write(bytes, 0, len);
}
fis.close();
}
} catch (Exception e) {
error += ","+msg;
e.printStackTrace();
} finally {
zos.flush();
zos.close();
}