引用类型的变量,只有指向同一个对象时,==才会返回true.
基本类型不能和引用类型进行比较.
&&会短路,但是&不会短路.同样的||会短路,|就不会短路.
^异或,两个操作数不同时返回true,相同返回false.
数组的两种初始化方式:两种方法,前面的括号里都不要写数字!
int[] array=new int[]{0,1,2,3};//这种方式千万不要在中括号里写数字!!
int[] array=new int[4]//此时数组里都是默认0.
Arrays数组工具类,提供许多强大的静态方法,比如
void sort(type[] a)//对a数组进行排序
形参类型后加三个点,表示可以接受多个此类型的形参.但可变形参只能位于参数列表的最后.
private:同一个类才可以访问
default(默认):同一个类,同一个包中可访问
protected:同一个类,同一个包,子类中可访问
public:全局范围可访问
局部变量不要使用修饰符!!!
关于多态,编译(成员变量)看左(父类),运行(成员方法)看右(子类).
instanceof 运算符,判断前面变量是否是后面类或其子类的实现.是就返回true,否就返回false
用final修饰父类,则其不允许被继承.
初始化块,前面的先执行.它要么用static修饰,要么没有修饰符.
创建对象时,先执行初始化块,再执行构造方法.如果用static修饰,则是静态初始化块,在创建类的时候就会执行,不会等到创建对象的时候再执行.
那么类什么时候创建呢?当jvm第一次使用某个类时.
String有一个valueOf()方法,可以将其他类型转换为String,同样其他包装类也有parseXxx(String s)静态方法,将String转换为其对应类型.
默认的equals就是==,想要不一样的,那就自己重写equals()方法.
final修饰的成员变量必须由程序员显式的指定初始值
先继承父类,再实现接口
枚举类必须在第一行列出所有枚举值.(默认用public static final 修饰)
一个枚举类举例,知道这么用枚举类就好了,其他的不用记:
public enum ExceptionEnum {
GROUP_NOT_FOUNT(500,"规格分组未找到"),
FILE_TYPE_NOT_ALLOWED(500,"非法文件类型"),
FILE_UPLOAD_ERROR(500,"文件上传失败"),
CATEGORY_BRAND_SAVE_ERROR(500,"新增品牌分类失败"),
BRAND_SAVE_ERROR(500,"新增品牌失败"),
PRICE_CANNOT_BE_NULL(400,"价格不能为空"),
CATEGORY_NOT_FOUND(404,"商品分类没查到"),
BRAND_NOT_FOUNT(404,"品牌没有找到"),
PARAM_NOT_FOUND(500,"规格参数未找到")
;//以上是所有的枚举值,并且有参数,下面是枚举值所具有的参数.
private int code;
private String msg;
}
所有静态的成员不允许使用范型,构造方法声明时也不允许使用范型.
同步代码块使用方法:将想要线程安全的代码块放到下面的大括号里:
synchronized (obj){
//其中obj是随便一个监视器,一般就用this就好
}
或者是在方法上加上synchronized修饰,表示这是一个线程安全的方法.
匿名内部类就是一个没有类名的类,直接new,而lambda更直接,连类的体和方法框架都省略了,直接就是,参数,加方法内部内容.恩恩,就是这样.不难理解的.
String有contains方法,用于看是否有某个字符.
List有sort方法,可以跟据传入规则排序.
数组的静态方法类是Arrays,list的静态方法类是Collections
[StringUtils工具类常用方法]
前言:工作中看到项目组里的大牛写代码大量的用到了StringUtils工具类来做字符串的操作,便学习整理了一下,方便查阅。
- isEmpty(String str) 是否为空,空格字符为false
- isNotEmpty(String str) 是否为非空,空格字符为true
- isBlank(String str) 是否为空,空格字符为true
- isNotBlank(String str) 是否为非空,空格字符为false
- trim(String str)去除字符串两端的控制符,空字符串、null 返回 null
- trimToEmpty(String str) 去除字符串两端的控制符,空字符串、null 返回""
- stripToNull(String str) 去除字符串两端的空白符,空字符串、null 返回null
- stripToEmpty(String str) 去除字符串两端的空白符,空字符串、null 返回""
- strip(String str, String stripChars) 去掉str两端的在stripChars中的字符
StringUtils.strip("000000134_76539000","0")="134_76539"
- stripStart (String str,String stripChars) 去除str 前端在stripChars中的字符
- stripEnd (String str,String stripChars) 去除str 后端在stripChars中的字符
- equals(String str1,String str2) 比较两个字符串是否相等,如果两个均为空则认为相等
- indexOf(String str,char searchChar) 返回searchChar 在字符串中第一次出现的位置,如果没找到则返回 -1,如果str 为null 或者 "",也返回-1
- indexOf(String str,char searchChar,int startPos) 返回字符searchChar从startPos开始在字符串str中第一次出现的位置。
- contains(String str,char searchChar) str中是否包含字符searchChar,str为null 或者 searchChar为null,返回false 。
StringUtils.contains("", "") = true
StringUtils.contains("dfg", "") = true
- containsIgnoreCase(String str,String searchStr) str中是否包含字符searchChar,不区分大小写
- int indexOfAny(String str, char[] searchChars) 找出字符数组searchChars中的字符第一次出现在字符串str中的位置。 如果字符数组中的字符都不在字符串中,则返回-1 ,如果字符串为null或"",则返回-1
- subString(String str,int start) 从start 开始,包含start 那个字符,得到字符串str 的子串,如果start为负数,则从后面开始数起。如果str 为null 或者 "" 则返回其本身
- subStringBefore(String str,String separator) 得到字符串separator第一次出现前的子串。不包含那个字符,如果str 为null 或者 "" 则返回其本身。
- subStringAfter(String str,String separator) 得到字符串separator第一次出现后的子串,不包含那个字符,如果 str 为null,或者"",则返回其本身
- subString(String str,int start,int end) 同上
- left(String str,int len) 得到字符串str从左边数len长度的子串,如果str 为null 或者 "",则返回其本身,如果len小于0,则返回""
- right(String str,int len)得到字符串str从右边数len长度的子串
- mid(String str,int pos,int len) 得到字符串str从pos开始len长度的子串,pos小于0,则设为0。
- split(String str) 把字符串拆分成一个字符串数组,用空白符 作为分隔符,字符串为null 返回null,字符串为"",返回空数组{}
- split(String str,char c) 按照 char c 拆分字符串
- join(Object[] arrey)把数组中的元素连接成一个字符串返回
- join(Object[] arrey,char c) 把数组中的元素拼接成一个字符串返回,把分隔符 c 也带上
- deleteWhitespace(String str) 删除字符串中的所有空白符,包括转义字符
- removeStart(String str,String remove) 如果字符串str是以remove开始,则去掉这个开始,然后返回,否则返回原来的串
- removeEnd(String str,String remove) 如果字符串str是以字符串remove结尾,则去掉这个结尾,然后返回,否则返回原来的串。
- remove(String str,char remove) 去掉字符串str中所有包含remove的部分,然后返回
- replace(String str,String reql,String with) 在字符串text中用with代替repl,替换所有
- replaceChars(String str,char old,char new) 在字符串中 new 字符代替 old 字符
- replaceChars(String str, String searchChars, String replaceChars) 这个有点特别,先看下面三个例子
StringUtils.replaceChars("asssdf","s","yyy")) = "ayyydf"
StringUtils.replaceChars("asdf","sd","y")) = "ayf"
StringUtils.replaceChars("assssddddf","sd","y"))= "ayyyyf"
解释:为什么会出现上面这样的结果呢?原来这个置换规则是这样的,他是拿searchChars的index,去replaceChars找相应的index然后替换掉,怎么说呢?比如说第一个例子 s 的index 是0,找到yyy相对应的index为0的字符是y。第二个例子 's' 的index是0,'d'的index是1, 字符's' 可以找到对应index为0的 'y',d就找不到index为'1'的的字符了,所以就直接过滤掉了,听明白了吗?
overlay(String str,String new,int start,int end) 用字符串new 覆盖字符串str从start 到 end 之间的串
chop(String str) 去掉字符串的最后一个字符,比如/r/n
repeat(String str,int repart) 重复字符串repeat次
rightPad(String str,int size,String padStr) size长度的字符串,如果不够用padStr补齐
leftPad(String str,int size,String padStr)同上
center(String str,int size)产生一个字符串,长度等于size,str位于新串的中心
swapCase(String str) 字符串中的大写转小写,小写转换为大写
关于JAVA Stream操作
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
JDK8中有双冒号的用法,就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。
字符串不能用==来比较,要用equals来比较
集合用toArray()转变为数组时默认转变的都是Object[ ],如果你想要一个确切类型的数组,那么请在toArray()方法里传入一个对新类型的数组,比如toArray(new String[0]),这样返回的就是字符串数组了.就这样,开始,加油!走起!
所有list,set,map都可以用stream方法,数组的话可以用Stream.of静态方法来生成流
filter()是过滤函数,当你写这个函数时,一定要记得返回布尔值.
boolean数组默认值是false;
integer类型不要随便比较大小,不准确的,要比较大小就换成int.
关于快慢指针,可以用于查找链表的中点,因为快指针永远是慢指针速度的两倍,所以当快指针到达终点时,慢指针刚好在链表的中点.
在多线程里,sleep()和suspend()不会释放资源,wait()和await()会释放资源
HashMap允许key为null,它是线程不安全的.
char的默认值是'\u0000'
关于字符串的创建:
1.直接使用双引号创建字符串
判断这个常量是否存在于常量池,
如果存在,
判断这个常量是存在的引用还是常量,
如果是引用,返回引用地址指向的堆空间对象,
如果是常量,则直接返回常量池常量,
如果不存在,
在常量池中创建该常量,并返回此常量
String a1 = "AA";//在常量池上创建常量AA
String a2 = "AA";//直接返回已经存在的常量AA
System.out.println(a1 == a2); //true
String a3 = new String("AA"); //在堆上创建对象AA
a3.intern(); //在常量池上创建对象AA的引用
String a4 = "AA"; //常量池上存在引用AA,直接返回该引用指向的堆空间对象,即a3
System.out.println(a3 == a4); //false,如果这个例子不理解,请看完整篇文章再回来看这里
2.new String创建字符串
首先在堆上创建对象(无论堆上是否存在相同字面量的对象),
然后判断常量池上是否存在字符串的字面量,
如果不存在
在常量池上创建常量
如果存在
不做任何操作
String a1 = new String("AA");
String a2 = new String("AA");
System.out.println(a1 == a2); //false
//如果常量池上不存在常量AA,也不存在引用AA,则创建常量AA
String a1 = new String("AA");
System.out.println(a1 == a1.intern()); //false
3.双引号相加
判断这两个常量、相加后的常量在常量池上是否存在
如果不存在
则在常量池上创建相应的常量
如果存在
判断这个常量是存在的引用还是常量,
如果是引用,返回引用地址指向的堆空间对象,
如果是常量,则直接返回常量池常量,
String a1 = "AA" + "BB";//在常量池上创建常量AA、BB和AABB,并返回AABB
//常量池上存在常量AABB
String a2 = "AABB";
String a3 = "AA" + "BB";
System.out.println(a2 == a3); //true
//常量池上存在引用AABB
String a4 = new String("AA") + new String("BB"); //在堆上创建对象AA、BB和AABB,在常量池上创建常量AA和BB
a4.intern();
String a5 = "AA" + "BB";
System.out.println(a4 == a5); //false
4.两个new string 相加
首先会创建这两个对象以及相加后的对象
然后判断常量池中是否存在这两个对象的字面量常量
如果存在
不做任何操作
如果不存在
则在常量池上创建对应常量
//常量AA不存在,所以第一步在常量池中创建了常量AA
String a2 = new String("AA") + new String("BB");
String a3 = new String("A")+new String("A"); //创建对象AA
System.out.println(a3 == a3.intern()); //false
//只在堆上创建AABB对象,没有在常量池中创建常量AABB
String a2 = new String("AA") + new String("BB");
System.out.println(a2 == a2.intern()); //true
5.双引号字符串与new string 字符串
首先创建两个对象,一个是new String的对象,一个是相加后的对象
然后判断双引号常量与new String的字面量在常量池是否存在
如果存在
不做操作
如果不存在
则在常量池上创建对象的常量
String a1 = "AABB";
String a2 = "AA" + new String("BB");
System.out.println(a1 == a2.intern());//true
System.out.println(a2 == a2.intern()); //false
6.String.intern() 分析
判断这个常量是否存在于常量池。
如果存在
判断存在内容是引用还是常量,
如果是引用,
返回引用地址指向堆空间对象,
如果是常量,
直接返回常量池常量
如果不存在,
将当前对象引用复制到常量池,并且返回的是当前对象的引用
String a1 = "AA";
System.out.println(a1 == a1.intern()); //true
String a2 = new String("B") + new String("B");
a2.intern();
String a3 = new String("B") + new String("B");
System.out.println(a2 == a3.intern());//true
System.out.println(a3 == a3.intern());//false
String a4 = new String("C") + new String("C");
System.out.println(a4 == a4.intern()); //true
调用线程的sleep方法,会释放其他资源,但是不会释放同步监视器.yield也不会释放同步监视器.
wait()方法会自动释放目标对象的锁.await()也是一样的
volatile 提醒虚拟机小心处理此对象,并保证数据的可见性和有序性.
Arrays.sort和Collections.sort()一样,要想自定义排序,只能传入非原始类型进去,也就是说,int不行,只能用Integer
子类不会继承父类的构造方法.
接口中的变量默认是public static final 的,方法默认是public abstract 的
所有静态的东西不允许使用范型
sql中的字符串是用单引号引起来的.
Maven
什么是Maven?
如今我们构建一个项目需要用到很多第三方的类库,如写一个使用Spring的Web项目就需要引入大量的jar包。一个项目Jar包的数量之多往往让我们瞠目结舌,并且Jar包之间的关系错综复杂,一个Jar包往往又会引用其他Jar包,缺少任何一个Jar包都会导致项目编译失败。
以往开发项目时,程序员往往需要花较多的精力在引用Jar包搭建项目环境上,而这一项工作尤为艰难,少一个Jar包、多一个Jar包往往会报一些让人摸不着头脑的异常。
而Maven就是一款帮助程序员构建项目的工具,我们只需要告诉Maven需要哪些Jar 包,它会帮助我们下载所有的Jar,极大提升开发效率。
安装Maven 和 Maven的Eclipse插件
http://blog.csdn.net/qjyong/article/details/9098213
Maven规定的目录结构
若要使用Maven,那么项目的目录结构必须符合Maven的规范,其目录结构如下:
Maven基本命令
-v:查询Maven版本
本命令用于检查maven是否安装成功。
Maven安装完成之后,在命令行输入mvn -v,若出现maven信息,则说明安装成功。
compile:编译
将java源文件编译成class文件
test:测试项目
执行test目录下的测试用例
package:打包
将项目打成jar包
clean:删除target文件夹
install:安装
将当前项目放到Maven的本地仓库中。供其他项目使用
什么是Maven仓库?
Maven仓库用来存放Maven管理的所有Jar包。分为:本地仓库 和 中央仓库。
- 本地仓库:Maven本地的Jar包仓库。
- 中央仓库: Maven官方提供的远程仓库。
当项目编译时,Maven首先从本地仓库中寻找项目所需的Jar包,若本地仓库没有,再到Maven的中央仓库下载所需Jar包。
什么是“坐标”?
在Maven中,坐标是Jar包的唯一标识,Maven通过坐标在仓库中找到项目所需的Jar包。
如下代码中,groupId和artifactId构成了一个Jar包的坐标。
<dependency>
<groupId>cn.missbe.web.search</groupId>
<artifactId>resource-search</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
</dependency>
- groupId:所需Jar包的项目名
- artifactId:所需Jar包的模块名
- version:所需Jar包的版本号
传递依赖 与 排除依赖
- 传递依赖:如果我们的项目引用了一个Jar包,而该Jar包又引用了其他Jar包,那么在默认情况下项目编译时,Maven会把直接引用和简洁引用的Jar包都下载到本地。
- 排除依赖:如果我们只想下载直接引用的Jar包,那么需要在pom.xml中做如下配置:(将需要排除的Jar包的坐标写在中)
<exclusions>
<exclusion>
<groupId>cn.missbe.web.search</groupId>
<artifactId>resource-search</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
</exclusion>
</exclusions>
依赖范围scope
在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。
- compile :默认范围,用于编译
- provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath
- runtime: 在执行时需要使用
- test: 用于test任务时使用
- system: 需要外在提供相应的元素。通过systemPath来取得
- systemPath: 仅用于范围为system。提供相应的路径
- optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用
依赖冲突
若项目中多个Jar同时引用了相同的Jar时,会产生依赖冲突,但Maven采用了两种避免冲突的策略,因此在Maven中是不存在依赖冲突的。
- 短路优先
本项目——>A.jar——>B.jar——>X.jar
本项目——>C.jar——>X.jar
本项目——>A.jar——>B.jar——>X.jar
本项目——>C.jar——>X.jar
若本项目引用了A.jar,A.jar又引用了B.jar,B.jar又引用了X.jar,并且C.jar也引用了X.jar。
在此时,Maven只会引用引用路径最短的Jar。
声明优先
若引用路径长度相同时,在pom.xml中谁先被声明,就使用谁。
聚合
什么是聚合?
将多个项目同时运行就称为聚合。
如何实现聚合?
只需在pom中作如下配置即可实现聚合:
<modules>
<module>web-connection-pool</module>
<module>web-java-crawler</module>
</modules>
继承
什么是继承?
在聚合多个项目时,如果这些被聚合的项目中需要引入相同的Jar,那么可以将这些Jar写入父pom中,各个子项目继承该pom即可。
如何实现继承?
- 父pom配置:将需要继承的Jar包的坐标放入标签即可。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.missbe.web.search</groupId>
<artifactId>resource-search</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
- 子pom配置:
<parent>
<groupId>父pom所在项目的groupId</groupId>
<artifactId>父pom所在项目的artifactId</artifactId>
<version>父pom所在项目的版本号</version>
</parent>
<parent>
<artifactId>resource-search</artifactId>
<groupId>cn.missbe.web.search</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
使用Maven构建Web项目
New Maven项目:选择WebApp:
若使用JSP,需添加Servlet依赖:
注:Servlet依赖只在编译和测试时使用!
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<!-- 只在编译和测试时运行 -->
<scope>provided</scope>
</dependency>
- 在Bulid Path中设置resource输出目录:
- 勾选:Dynamic Web Module
- 删掉测试目录
- 在pom中加入jetty的插件,并设置JDK版本:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.10.v20160621</version>
<executions>
<execution>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
运行项目:
输入:jetty:run
访问127.0.0.1:8080
若出现如下界面,表示成功!
pom.xml详解
pom.xml是Maven的核心,你的项目需要什么Jar包就在pom.xml里面配置。当编译项目时Maven读取该文件,并从仓库中下载相应的Jar包。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd">
<!--父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和 version。-->
<parent>
<!--被继承的父项目的构件标识符-->
<artifactId/>
<!--被继承的父项目的全球唯一标识符-->
<groupId/>
<!--被继承的父项目的版本-->
<version/>
</parent>
<!--声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候确保稳定性。-->
<modelVersion>4.0.0</modelVersion>
<!--项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径/com/mycompany/app-->
<groupId>cn.missbe.web</groupId>
<!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个 特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源码,二进制发布和WARs等。-->
<artifactId>search-resources</artifactId>
<!--项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型-->
<packaging>war</packaging>
<!--项目当前版本,格式为:主版本.次版本.增量版本-限定版本号-->
<version>1.0-SNAPSHOT</version>
<!--项目的名称, Maven产生的文档用-->
<name>search-resources</name>
<!--项目主页的URL, Maven产生的文档用-->
<url>http://www.missbe.cn</url>
<!-- 项目的详细描述, Maven 产生的文档用。 当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,就可以包含HTML标 签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的索引页文件,而不是调整这里的文档。-->
<description>A maven project to study maven.</description>
<!--描述了这个项目构建环境中的前提条件。-->
<prerequisites>
<!--构建该项目或使用该插件所需要的Maven的最低版本-->
<maven/>
</prerequisites>
<!--构建项目需要的信息-->
<build>
<!--该元素设置了项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->
<sourceDirectory/>
<!--该元素设置了项目脚本源码目录,该目录和源码目录不同:绝大多数情况下,该目录下的内容 会被拷贝到输出目录(因为脚本是被解释的,而不是被编译的)。-->
<scriptSourceDirectory/>
<!--该元素设置了项目单元测试使用的源码目录,当测试项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。-->
<testSourceDirectory/>
<!--被编译过的应用程序class文件存放的目录。-->
<outputDirectory/>
<!--被编译过的测试class文件存放的目录。-->
<testOutputDirectory/>
<!--使用来自该项目的一系列构建扩展-->
<extensions>
<!--描述使用到的构建扩展。-->
<extension>
<!--构建扩展的groupId-->
<groupId/>
<!--构建扩展的artifactId-->
<artifactId/>
<!--构建扩展的版本-->
<version/>
</extension>
</extensions>
<!--这个元素描述了项目相关的所有资源路径列表,例如和项目相关的属性文件,这些资源被包含在最终的打包文件里。-->
<resources>
<!--这个元素描述了项目相关或测试相关的所有资源路径-->
<resource>
<!-- 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例 子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。-->
<targetPath/>
<!--是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。-->
<filtering/>
<!--描述存放资源的目录,该路径相对POM路径-->
<directory/>
<!--包含的模式列表,例如**/*.xml.-->
<includes/>
<!--排除的模式列表,例如**/*.xml-->
<excludes/>
</resource>
</resources>
<!--这个元素描述了单元测试相关的所有资源路径,例如和单元测试相关的属性文件。-->
<testResources>
<!--这个元素描述了测试相关的所有资源路径,参见build/resources/resource元素的说明-->
<testResource>
<targetPath/><filtering/><directory/><includes/><excludes/>
</testResource>
</testResources>
<!--构建产生的所有文件存放的目录-->
<directory/>
<!--产生的构件的文件名,默认值是${artifactId}-${version}。-->
<finalName/>
<!--当filtering开关打开时,使用到的过滤器属性文件列表-->
<filters/>
<!--子项目可以引用的默认插件信息。该插件配置项直到被引用时才会被解析或绑定到生命周期。给定插件的任何本地配置都会覆盖这里的配置-->
<pluginManagement>
<!--使用的插件列表 。-->
<plugins>
<!--plugin元素包含描述插件所需要的信息。-->
<plugin>
<!--插件在仓库里的group ID-->
<groupId/>
<!--插件在仓库里的artifact ID-->
<artifactId/>
<!--被使用的插件的版本(或版本范围)-->
<version/>
<!--是否从该插件下载Maven扩展(例如打包和类型处理器),由于性能原因,只有在真需要下载时,该元素才被设置成enabled。-->
<extensions/>
<!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。-->
<executions>
<!--execution元素包含了插件执行需要的信息-->
<execution>
<!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标-->
<id/>
<!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段-->
<phase/>
<!--配置的执行目标-->
<goals/>
<!--配置是否被传播到子POM-->
<inherited/>
<!--作为DOM对象的配置-->
<configuration/>
</execution>
</executions>
<!--项目引入插件所需要的额外依赖-->
<dependencies>
<!--参见dependencies/dependency元素-->
<dependency>
......
</dependency>
</dependencies>
<!--任何配置是否被传播到子项目-->
<inherited/>
<!--作为DOM对象的配置-->
<configuration/>
</plugin>
</plugins>
</pluginManagement>
<!--使用的插件列表-->
<plugins>
<!--参见build/pluginManagement/plugins/plugin元素-->
<plugin>
<groupId/><artifactId/><version/><extensions/>
<executions>
<execution>
<id/><phase/><goals/><inherited/><configuration/>
</execution>
</executions>
<dependencies>
<!--参见dependencies/dependency元素-->
<dependency>
......
</dependency>
</dependencies>
<goals/><inherited/><configuration/>
</plugin>
</plugins>
</build>
<!--模块(有时称作子项目) 被构建成项目的一部分。
列出的每个模块元素是指向该模块的目录的相对路径-->
<modules/>
<!--发现依赖和扩展的远程仓库列表。-->
<repositories>
<!--包含需要连接到远程仓库的信息-->
<repository>
<!--如何处理远程仓库里发布版本的下载-->
<releases>
<!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
<enabled/>
<!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。-->
<updatePolicy/>
<!--当Maven验证构件校验文件失败时该怎么做:ignore(忽略),fail(失败),或者warn(警告)。-->
<checksumPolicy/>
</releases>
<!-- 如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,
POM就可以在每个单独的仓库中,为每种类型的构件采取不同的 策略。
例如,可能有人会决定只为开发目的开启对快照版本下载的支持。
参见repositories/repository/releases元素 -->
<snapshots>
<enabled/><updatePolicy/><checksumPolicy/>
</snapshots>
<!--远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库-->
<id>banseon-repository-proxy</id>
<!--远程仓库名称-->
<name>banseon-repository-proxy</name>
<!--远程仓库URL,按protocol://hostname/path形式-->
<url>http://192.168.1.169:9999/repository/</url>
<!-- 用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。Maven 2为仓库提供了一个默认的布局;然 而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。-->
<layout>default</layout>
</repository>
</repositories>
<!--发现插件的远程仓库列表,这些插件用于构建和报表-->
<pluginRepositories>
<!--包含需要连接到远程插件仓库的信息.参见repositories/repository元素-->
<pluginRepository>
......
</pluginRepository>
</pluginRepositories>
<!--该元素描述了项目相关的所有依赖。 这些依赖组成了项目构建过程中的一个个环节。
它们自动从项目定义的仓库中下载。要获取更多信息,请看项目依赖机制。-->
<dependencies>
<dependency>
<!--依赖的group ID-->
<groupId>org.apache.maven</groupId>
<!--依赖的artifact ID-->
<artifactId>maven-artifact</artifactId>
<!--依赖的版本号。 在Maven 2里, 也可以配置成版本号的范围。-->
<version>3.8.1</version>
<!-- 依赖类型,默认类型是jar。它通常表示依赖的文件的扩展名,但也有例外
。一个类型可以被映射成另外一个扩展名或分类器。类型经常和使用的打包方式对应,
尽管这也有例外。一些类型的例子:jar,war,ejb-client和test-jar。
如果设置extensions为 true,就可以在 plugin里定义新的类型。所以前面的类型的例子不完整。-->
<type>jar</type>
<!-- 依赖的分类器。分类器可以区分属于同一个POM,但不同构建方式的构件。
分类器名被附加到文件名的版本号后面。例如,如果你想要构建两个单独的构件成 JAR,
一个使用Java 1.4编译器,另一个使用Java 6编译器,你就可以使用分类器来生成两个单独的JAR构件。-->
<classifier></classifier>
<!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。
- compile :默认范围,用于编译
- provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath
- runtime: 在执行时需要使用
- test: 用于test任务时使用
- system: 需要外在提供相应的元素。通过systemPath来取得
- systemPath: 仅用于范围为system。提供相应的路径
- optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用-->
<scope>test</scope>
<!--仅供system范围使用。注意,不鼓励使用这个元素,
并且在新的版本中该元素可能被覆盖掉。该元素为依赖规定了文件系统上的路径。
需要绝对路径而不是相对路径。推荐使用属性匹配绝对路径,例如${java.home}。-->
<systemPath></systemPath>
<!--当计算传递依赖时, 从依赖构件列表里,列出被排除的依赖构件集。
即告诉maven你只依赖指定的项目,不依赖项目的依赖。此元素主要用于解决版本冲突问题-->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!--可选依赖,如果你在项目B中把C依赖声明为可选,你就需要在依赖于B的项目(例如项目A)中显式的引用对C的依赖。可选依赖阻断依赖的传递性。-->
<optional>true</optional>
</dependency>
</dependencies>
<!-- 继承自该项目的所有子项目的默认依赖信息。这部分的依赖信息不会被立即解析,
而是当子项目声明一个依赖(必须描述group ID和 artifact ID信息),
如果group ID和artifact ID以外的一些信息没有描述,
则通过group ID和artifact ID 匹配到这里的依赖,并使用这里的依赖信息。-->
<dependencyManagement>
<dependencies>
<!--参见dependencies/dependency元素-->
<dependency>
......
</dependency>
</dependencies>
</dependencyManagement>
<!--项目分发信息,在执行mvn deploy后表示要发布的位置。
有了这些信息就可以把网站部署到远程服务器或者把构件部署到远程仓库。-->
<distributionManagement>
<!--部署项目产生的构件到远程仓库需要的信息-->
<repository>
<!--是分配给快照一个唯一的版本号(由时间戳和构建流水号)
还是每次都使用相同的版本号?参见repositories/repository元素-->
<uniqueVersion/>
<id>banseon-maven2</id>
<name>banseon maven2</name>
<url>file://${basedir}/target/deploy</url>
<layout/>
</repository>
<!--构件的快照部署到哪里?如果没有配置该元素,默认部署到repository元素配置的仓库,
参见distributionManagement/repository元素-->
<snapshotRepository>
<uniqueVersion/>
<id>banseon-maven2</id>
<name>Banseon-maven2 Snapshot Repository</name>
<url>scp://svn.baidu.com/banseon:/usr/local/maven-snapshot</url>
<layout/>
</snapshotRepository>
<!--部署项目的网站需要的信息-->
<site>
<!--部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置-->
<id>banseon-site</id>
<!--部署位置的名称-->
<name>business api website</name>
<!--部署位置的URL,按protocol://hostname/path形式-->
<url>
scp://svn.baidu.com/banseon:/var/www/localhost/banseon-web
</url>
</site>
<!--项目下载页面的URL。如果没有该元素,用户应该参考主页。
使用该元素的原因是:帮助定位那些不在仓库里的构件(由于license限制)。-->
<downloadUrl/>
<!-- 给出该构件在远程仓库的状态。不得在本地项目中设置该元素,
因为这是工具自动更新的。有效的值有:none(默认),
converted(仓库管理员从 Maven 1 POM转换过来),partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部 署),verified(被核实时正确的和最终的)。-->
<status/>
</distributionManagement>
<!--以值替代名称,Properties可以在整个POM中使用,也可以作为触发条件(见settings.xml配置文件里activation元素的说明)。格式是<name>value</name>。-->
<properties/>
</project>
maven的使用可参见:https://blog.csdn.net/qq_22172133/article/details/81666926
默认的clone方法,只能浅拷贝,对于数组来说够用了.深拷贝需要自己写.
IDEA(eclipse复制版常用快捷键)
Ctrl + / 单行注释
ctrl + shift + / 多行注释
/ + 回车 文档注释**
alt + ↑或者↓ 代码向上/向下移动
ctrl + alt + ↑或者↓ 代码向上或者向下移动
crtl + pageup/pagedown 不同标签页之间的切换
home/end 行首或行末
ctrl + home/end 文章首或者文章末
shift + ↑ 选中单词
ctrl + shift + ↑或者↓ 移动光标到上一个方法或下一个方法.
crtl + z 撤销
crtl + y重做(把撤销的再做一遍)
alt + shift + r 重命名
ctrl + shift + x / ctrl + shift + u大小写转换.
ctrl + shift + y 翻译
F2或 ctrl + shift + space 打开文档
ctrl + F 文档内搜索
shift + shift 全局搜索
ctrl+ alt +U 打开类继承树
ctrl+ alt +U + shift 打开大图继承树
alt + shift + ↑ 选中单词
ctrl + ↑或者↓ 上下移动屏幕
alt + shift + L 提取变量
ctrl + shift + o 自动导入包
ctrl + shift + f 格式化文档
ctrl + shift + p 回到另一个括号的位置
ctrl + T 打开方法的实现
F3查看声明
alt + ←或→ 上一个编辑的位置
ctrl + F3 文件结构
F4查看类的继承结构
ctrl + shift + h 方法层次结构
alt + insert 生成
ctrl + shift + enter 向上生成一个空行
shift + enter 向下生成一个空行
alt + enter 快速猜测你的意图
shift + alt + o高亮显示
ctrl + - 收缩代码,
ctrl + + 展开代码
ctrl + * 展开所有代码
ctrl + shift + / 折叠所有代码
Ctrl+Shift+=:展开所有代码
Ctrl+Shift+-:收缩所有代码
ctrl + W 快速全屏
ctrl + F11(alt + shift + X) 运行程序,
把一段函数内的代码抽取成方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用) |
Alt+Shift+Z 包围代码
ctrl + B加粗显示(用在Markdown等文本编辑器里)
ctrl + e 快速在文档之间进行转换.
ctrl + `进行配色方案切换
ctrl + enter 可以快速执行sql执行
ctrl + j 可以快速进行查找,定位光标
ctrl + alt + s 快速打开设置
连按两下alt键并且不放开,可以打开隐藏的选项卡
关于后缀补全:
1.bool值后面加个.if可以快速进行if包围,
2.变量后面加个.var可以快速生成变量.
3 .null可以判断对象是否为空,
4 .notnull(或者.nn)判断是否非空
5.for遍历(增强型遍历)。
list.for
6.fori遍历(带索引的遍历)。
list.fori
7.not对布尔类型取反。
isSuccess.not
8.if条件判断。
list.length > 0.if
isSuccess.if
9.cast强转对象/数据类型。
student.cast
10.return返回值。
"yanggb".return
student.return
list.return
new Student().return
关于各个数据类型的字节数.
Java集合的继承关系
Java里面写文件用这种方式:C:\\Users\\Administrator.USER-20190316CX\\Desktop\\研究生
或者是直接用一个正斜杠/
Java里设置时间的方法:
Date date = new Date(System.currentTimeMillis);
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
System.out.println(dateFormat.format(date));
将随机的字符串转换为UUID:
UUID.nameUUIDFromBytes((proName).getBytes()).toString()
关于Swagger的知识:
1、描述
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
作用:
1.接口的文档在线自动生成。
2.功能测试。
2、运用
a) maven导入Swagger
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
b) 创建Swagger2配置类
/**
* @program: jpademo
* @description: Swagger
* @author: ZengGuangfu
* @create 2018-10-24 10:12
*/
@Configuration
@EnableSwagger2
public class Swagger {
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.springbootjpa.jpademo.controller"))
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("利用swagger2构建的API文档")
.description("用restful风格写接口")
.termsOfServiceUrl("")
.version("1.0")
.build();
}
}
如上所示,docket() 方法创建Docket的Bean对象,apiInfo()则是创建ApiInfo的基本信息。
链式方法解析:
3、注解及其说明
@Api : 用在类上,说明该类的主要作用。
@ApiOperation:用在方法上,给API增加方法说明。
@ApiImplicitParams : 用在方法上,包含一组参数说明。
@ApiImplicitParam:用来注解来给方法入参增加说明。
apiParam.png
@ApiResponses:用于表示一组响应。
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
l code:数字,例如400
l message:信息,例如"请求参数没填好"
l response:抛出异常的类
@ApiModel:用在返回对象类上,描述一个Model的信息(一般用在请求参数无法使用@ApiImplicitParam注解进行描述的时候)
l @ApiModelProperty:描述一个model的属性
例子:
package com.example.springbootjpa.jpademo.controller;
import com.example.springbootjpa.jpademo.config.utils.SysNode;
import com.example.springbootjpa.jpademo.dao.EmployeeReposiroty;
import com.example.springbootjpa.jpademo.pojo.Employee;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.groups.Default;
import java.util.ArrayList;
import java.util.List;
/**
* @program: jpademo
* @description: EmployeeController
* @author: ZengGuangfu
* @create 2018-10-23 11:07
*/
@RestController
@RequestMapping("emp")
@Api(value = "用户管理类")
public class EmployeeController {
@Autowired
private EmployeeReposiroty employeeReposiroty;
/**
* 增加人物
* @param employee
* @return
*/
@PostMapping(value = "employee")
@ApiOperation(value = "新增一个用户",notes = "新增之后返回对象")
@ApiImplicitParam(paramType = "query",name = "employee",value = "用户",required = true)
@ApiResponse(code = 400,message = "参数没有填好",response = String.class)
public String insert(Employee employee){
Employee employee1 = employeeReposiroty.save(employee);
if(employee1 != null) {
return SysNode.Judge.SUCCESS.getResult();
}else {
return SysNode.Judge.FAILD.getResult();
}
}
/**
* 删除单个用户
* @param id
* @return
*/
@DeleteMapping(value = "employee/{id}")
@ApiOperation(value = "删除用户",notes = "根据成员id删除单个用户")
@ApiImplicitParam(paramType = "path",name = "id",value = "用户id",required = true,dataType = "Integer")
@ApiResponse(code = 400,message = "参数没有填好",response = String.class)
public String delete(@PathVariable("id")Integer id){
try{
employeeReposiroty.deleteById(id);
return SysNode.Judge.SUCCESS.getResult();
}catch (Exception e){
e.printStackTrace();
return SysNode.Judge.FAILD.getResult();
}
}
/**
* 修改单个成员
* @param employee
* @return
*/
@PutMapping(value = "employee/{id}")
@ApiOperation(value = "修改用户信息",notes = "根据成员id修改单个用户")
@ApiImplicitParam(paramType = "path",name = "id",value = "用户id",required = true,dataType = "Integer")
public String update(Employee employee){
/**
* save方法如果参数属性缺失,会导致原本存在的数据为null
*/
Employee employee1 = employeeReposiroty.saveAndFlush(employee);
if (employee1 != null) {
return SysNode.Judge.SUCCESS.getResult();
}else {
return SysNode.Judge.FAILD.getResult();
}
}
/**
* 获取所有成员,升序排列
* @return
*/
@GetMapping(value = "employee/sort")
@ApiOperation(value = "查询全部用户",notes = "默认根据升序查询全部用户信息")
public List<Employee> findAll(){
Sort orders = new Sort(Sort.Direction.DESC,"employeeId");
List<Employee> employeeList = employeeReposiroty.findAll(orders);
return employeeList;
}
/**
* 获取所有成员,升序排列
* @return
*/
@GetMapping(value = "employee/pageSort")
@ApiOperation(value = "查询用户信息",notes = "查询用户信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query",name = "sort",value = "排序方式:asc|desc",dataType = "String",required = true),
@ApiImplicitParam(paramType = "query",name = "pagenumber",value = "第几页",dataType = "Integer",required = true),
@ApiImplicitParam(paramType = "query",name = "pageSize",value = "分页数",dataType = "Integer",required = true)
})
public List<Employee> findAllByPage(String sort,Integer pagenumber,Integer pageSize){
try {
Sort.Direction sortlast;
if("desc".equals(sort.toLowerCase())){
sortlast = Sort.Direction.DESC;
}else{
sortlast = Sort.Direction.ASC;
}
Sort orders = new Sort(sortlast, "employeeId");
Pageable pageable = new PageRequest(pagenumber, pageSize, orders);
Page<Employee> employeePage = employeeReposiroty.findAll(pageable);
List<Employee> employeeList = employeePage.getContent();
return employeeList;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 自定义拓展jpa,根据用户名查找单个用户
* @param username
* @return
*/
@GetMapping(value = "employee/find/{username}")
@ApiOperation(value = "查询用户信息",notes = "根据用户登录名查询该用户信息")
@ApiImplicitParam(paramType = "path",name = "username",value = "用户登录名",required = true,dataType = "String")
public Employee findByUsername(@PathVariable("username") String username){
List<Employee> employeeList = employeeReposiroty.findByUserNameOrderByEmployeeIdAsc(username);
if (employeeList != null && !employeeList.isEmpty()){
return employeeList.get(0);
}
return null;
}
/**
* 测试用
* @return
*/
@GetMapping(value = "employee/grade")
public List<Object[]> findEmployeeAndGrade(){
Pageable pageable = new PageRequest(0,3);
Page<Object[]> page = employeeReposiroty.findEmployeeAndGrade(pageable);
System.out.println(page.getTotalElements()+"----------结果总数------------");
System.out.println(page.getTotalPages()+"--------根据pageSize的总页数-----------");
System.out.println(page.getNumber()+"--------当前页数,pageNumber----------");
System.out.println(page.getNumberOfElements()+"--------当前页有几个数据--------");
System.out.println(page.getSize()+"---------PageSize-------------");
System.out.println(page.getSort()+"---------排序方式,没有则是'UNSORTED'----------");
List<Object[]> objects = page.getContent();
return objects;
}
}
4、测试登录 localhost:8080/swagger-ui.html
swagger-ui.png
API 操作测试,修改
testParam.png
testResult.png
5、@ApiModel 接收对象传参
注意: 在后台采用对象接收参数时,Swagger自带的工具采用的是JSON传参, 测试时需要在参数上加入@RequestBody,正常运行采用form或URL提交时候请删除。
例子:
/**
* @program: jpademo
* @description: Employee
* @author: ZengGuangfu
* @create 2018-10-23 10:20
*/
@Getter
@Setter
@Data
@Entity
@Table(name = "employee")
@ApiModel(value = "用户对象模型")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "employee_id")
@Min(value = 1,groups = Employee.Children.class)
private Integer employeeId;
@Column(name = "user_name",length = 20,nullable = true)
@ApiModelProperty(value = "userName",required = true)
private String userName;
@Column(nullable = true)
@Size(min = 0,max = 65,message = "年龄超过范围限制",groups = Employee.Audit.class)
@ApiModelProperty(value = "age",required = true)
private Integer age;
@Column(name="gra_id")
@ApiModelProperty(value = "graId",required = true)
//@Digits(integer = 12,fraction = 4) //限制必须为一个小数,且整数部分的 位数 不能超过integer,小数部分的 位数 不能超过fraction
private Integer graId;
public interface Audit{};
public interface Children{};
}
在接口里,方法前加一个default
关键字修饰,那么这个方法是可以有方法体的,也就是当没有人实现时,他就会使用默认方法.但注解里不能使用这个.
再写一个注解类时,类里面的方法后面加上 default 值
就表示该方法默认返回值返回的就是这个.
在VSCODE里,按住Ctrl + F12 转到方法以及接口的实现.