枚举
枚举基本设置
public class TestMB {
public static void main(String[] args) {
Week day = Week.Tue;
System.out.println(day); // Tue
// ordinal() 获取下标值,改变位置会受影响
System.out.println(day.ordinal()); // 2
System.out.println(day == Week.Tue); // true
}
}
enum Week {
Mon, Tue, Wed, Thu, Fri, Sat, Sun;
}
附带值的枚举设置
public class TestMB {
public static void main(String[] args) {
Week day = Week.Mon;
System.out.println(day); // Mon
System.out.println(day.dayValue); // 1
System.out.println(day == Week.Mon); // true
}
}
enum Week {
Mon(1), Tue(2), Wed(3), Thu(4), Fri(5), Sat(6), Sun(7);
public final int dayValue;
private Week(int weekDay) {
this.dayValue = weekDay;
}
}
附带多个属性,重写toString方法
public class TestMB {
public static void main(String[] args) {
Week day = Week.Mon;
System.out.println(day); // 星期一
System.out.println(day.chinese); // 星期一
System.out.println(day.dayValue); // 1
System.out.println(day == Week.Mon); // true
}
}
enum Week {
Mon(1, "星期一"), Tue(2, "星期二"), Wed(3, "星期三"), Thu(4, "星期四"), Fri(5, "星期五"), Sat(6, "星期六"), Sun(7, "星期日");
public final int dayValue;
public final String chinese;
private Week(int weekDay, String chinese) {
this.dayValue = weekDay;
this.chinese = chinese;
}
@Override
public String toString() {
return chinese;
}
}
注解
注解定义方式
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default ""; // 常用参数设置为value
}
源注解使用
@Target
@Target源注解,决定注解使用的位置
- 类或接口:ElementType.TYPE;
- 字段:ElementType.FIELD;
- 方法:ElementType.METHOD;
- 构造方法:ElementType.CONSTRUCTOR;
- 方法参数:ElementType.PARAMETER。
@Target定义的value实际上是ElementType[],如果只有一个元素的时候可以缩写
@Retention
@Retention定义注解的生命周期
- 仅编译期:RetentionPolicy.SOURCE;
- 仅class文件:RetentionPolicy.CLASS;
- 运行期:RetentionPolicy.RUNTIME。
- 默认为RetentionPolicy.CLASS;
通常自定义都为RetentionPolicy.RUNTIME。
@Repeatable 修饰后可以对同一个对象使用多次
@Inherited 子类可继承父类
@Documented 描述注解是否被抽取到api文档中
注解使用,使用动态代理的方式实现
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SetName {
String value() default "java";
}
public class SetNameProcessor {
public void parseMethod(final Class<?> clazz) throws Exception {
final Object obj = clazz.getConstructor(new Class[] {}).newInstance(new Object[] {});
final Method[] methods = clazz.getMethods();
for (final Method method : methods) {
final SetName setName = method.getAnnotation(SetName.class);
if (null != setName) {
method.invoke(obj, setName.value());
}
}
}
}
public class Test {
@SetName
public static void hello(String name) {
System.out.println("hello " + name);
}
@SetName("rose")
public static void hi(String name) {
System.out.println("hi " + name);
}
public static void main(String[] args) throws Exception {
final SetNameProcessor setNameProcessor = new SetNameProcessor();
setNameProcessor.parseMethod(Test.class);
}
}
运行结果
hello java
hi rose
springboot aop自定义注解
引入springboot web 和aop的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLog {
String value() default "";
}
使用aop处理注解
// 定义切面注解,才能被aop扫描
@Aspect
@Component
public class ApiLogAspect {
// 定义切点
@Pointcut("@annotation(com.ma.relearn.annotation.ApiLog)")
public void pointCut() {}
// 后置执行
@After("pointCut()")
public void After(JoinPoint joinPoint) throws ClassNotFoundException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String requestURI = request.getRequestURI();
String method = request.getMethod();
String params;
if (method.toLowerCase().equals("get")) {
params = request.getQueryString();
} else {
params = getParamsFromBody(request);
}
String message = getAspectDescription(joinPoint);
System.out.println("标记:" + message + " " + method + " " + requestURI + " " + params);
}
public String getAspectDescription(JoinPoint joinPoint) throws ClassNotFoundException {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(ApiLog.class).value());
break;
}
}
}
return description.toString();
}
public String getParamsFromBody(HttpServletRequest request) {
StringBuffer sb = new StringBuffer();
BufferedReader bufferedReader = null;
String content = "";
try {
bufferedReader = request.getReader() ;
char[] charBuffer = new char[1024];
int bytesRead;
while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
sb.append(charBuffer, 0, bytesRead);
}
} catch (IOException ex) {
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
}
}
}
return sb.toString();
}
}
测试
@RestController
public class Test {
@ApiLog("测试GET接口")
@GetMapping("/test")
public String test() {
return "test";
}
@ApiLog("测试POST接口")
@PostMapping("/test1")
public String test1() {
return "test1";
}
}
结果:
标记:测试GET接口 GET /test a=1
标记:测试POST接口 POST /test1 test=abc
流
InputStream
abstract int read() 从数据中读取一个字节,并返回,结尾时返回-1
int read(byte[] b) 数据读入到字节数组b[]中,并返回实际读取的数量,结尾时返回-1,最多读入byte.length个字节
int read(byte[] b, int off, int len) 读入一个字节数组,结尾时返回-1
- b 数据读入的数组
- off 偏移量
- len 读入字节数最大数量
long skip(long n) 输入流中跳过n个字节,返回实际跳过的字节数
int available() 返回不阻塞情况下可获取的字节数
void close() 关闭输入流
void mark(int readlimit) 在输入流的当前位置打一个标记。输入流中已经读入的字节多余readlimit个,忽略这个标记(不是所有流都支持)
void reset() 返回最后一个标记,随后read的调用会重新读入这写字节,如果没有标记,不会被重置
boolean markSupported() 判断是否支持标记,支持返回true
OutputStream
abstract void write(int n) 写一个字节的数据
void write(byte[] b)
void write(byte[] b, int off, int len)
- b 写出的数据
- off 偏移量
- len 写出数据的最大数量
void close() 关闭输出流
void flush() 冲刷输出流,将缓冲数据发送
InputStream、OutputStream、Reader 和 Writer 都实现了 Closeable 接口
附加接口:
1.Closeable
void close() 关闭,可能会抛出IOException
2.Flushable CharBuffer实现了该接口
void flush() 刷新缓冲区
3.Readable(CharBuffer cb)
int read() 尝试向cb读取可持有数量的char值
4.Appendable 只有Writer实现了
Appendable append(char c)
Appendable append(CharSequence cs) 向给定Appendable中追加码元
5.CharSequence
char charAt(int index) 返回给定索引处的码元
int length() 返回码元数量
CharSequence subSequence(int startIndex, int endIndex) 返回指定下标构成的新CharSequence
String toString() 返回码元构成的字符串
FileInputStream
FileInputStream(String name)
FileInputStream(File file)
创建一个新的文件输入流
FileOutputStream
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
创建一个新的文件输出流,如果append=true,数据会追加到文件尾,已有的文件不会被删除,否则会删除相同名字的已有文件
BufferedInputStream
BufferedInputStream(InputStream in)
创建一个带缓冲区的输入流,带缓冲区的输入流在从流中读取字符时,不会每次都对设备访问。当缓冲区为空时,会向缓冲区读入一个新的数据块
BufferedOutputStream
BufferedOutputStream(OutputStream out)
创建一个带缓冲区的输出流,带缓冲区的输出流在写出字符时,不会每次都会设备访问。当缓冲区被填满时,或者刷新缓冲区时,数据会写出
PushbackInputStream
PushbackInputStream(InputStream in)
PushbackInputStream(InputStream in, int size)
构建一个可以预览一个字节或者具有指定尺寸的回推缓冲区的流
void unread(int b)
回推一个字节,可以在下次read的时候再次获取,b表示要再次读入的字节