1. 在路径中获取类全限定名
用到常用api:
- indexOf(str)在当前字符串中查找str的起始位置
- substring(beginIndex )从beginIndex开始位置截取字符串到最后位置
substring(beginIndex, endIndex)从开始位置到结束位置中间的部分(包头不包尾) - s.length()字符串的长度
- s.replaceAll(Regex正则表达式)replaceAll(“\\”,“\.”)
代码示例:
/**
* 根据传过来的字节码文件路径解析出 类的全限定名
* 例如:F:\idea_Java\excellent\stage2\javaEE\spring\target\classes\com\lifeng\pojo\User.class
* 返回结果"com.lifeng.pojo.User
* 1、得到classes的起始位置序号
* 2、去掉 .class
* 3、将\\换成.
*/
@Test
public void getClassName() {
//String path = "F:\\idea_Java\\excellent\\stage2\\javaEE\\spring\\target\\classes\\com\\lifeng\\pojo\\User.class";
String path = "F:\\idea_Java\\excellent\\stage2\\javaEE\\mybatis\\target\\classes\\jdbc\\hh.class";
//定位到classes的起始位置,利用indexOf(),查找给定字符串在上面字符串当中的起始位置序号
Integer index = path.indexOf("classes");
System.out.println(index);
//截取classes之后的部分
String substring = path.substring(index+8);
System.out.println(substring);
//去掉.class
String s = substring.substring(0, substring.length() - 6);
System.out.println(s);
String replaceAll = s.replaceAll("\\\\", "\\.");
System.out.println(replaceAll);
}
2. 全路径获取类的实例名称(Bean)
开发步骤:
@Test
public void testBeanName() {
String beanName = getBeanName("ClassName");
System.out.println(beanName);
}
//工具类:把传入全路径截取出类名,首字母小写
/**
* 1、去掉前面的包名lastIndexOf
* 2、按最后一个.来截取到最后
* 3、把首字母小写
* @param className
* @return
*/
public static String getBeanName(String className) {
int lastIndexOf = className.lastIndexOf(".");
String s = className.substring(lastIndexOf + 1);
String lower = toFirstLower(s);
return lower;
}
//工具类:首字母小写
public static String toFirstLower(String name) {
char c = name.charAt(0); //得到指定索引处的字符
char toLowerCase = Character.toLowerCase(c); //将字符转成小写
return toLowerCase+name.substring(1); //得到将首字母转为小写的实例名
}
3. 遍历目录,得到所有文件
/**
* 分析
* 1、给定目录路径,利用file对象的API,listFiles得到第一层的文件列表
* 2、判断第一层是否有文件或目录,有目录则利用递归继续遍历
* 3、如果没有目录,则直接输出文件名
*/
public static void readClassName(String path) {
//创建file对象
File file = new File(path);
//得到该路径的文件列表
File[] files = file.listFiles();
//判断files是否为空,为空则代表是空目录,否则将继续遍历子目录,或者打印出文件名
if (files == null || files.length == 0) {
System.out.println("此目录为空");
} else {
for (File f : files) {
//判断是否是目录,true:遍历子目录
if (f.isDirectory()) {
System.out.println("遍历目录:"+f.getAbsolutePath());
readClassName(f.getAbsolutePath());
} else {
//输出文件
System.out.println(f.getAbsolutePath());
}
}
}
}
4. 简单爬虫、json解析
- 把java对象转换json串(序列化)
- 把json转成java对象(反序列化)
- 从json串中解析数据
注:业界有json工具包:- fastjson阿里(坑)
- 谷歌gson(坑)
- 业界最稳定:Jackson json,springmvc默认选择转换工具类
- 爬取京东商品价格,解析json
需要的jar包:
爬虫
public class TestJson {
//利用jackjson创建映射对象
private static final ObjectMapper MAPPER = new ObjectMapper();
//将java对象转成json字符串(序列化)
@Test
public void toJson() throws JsonProcessingException {
Dept dept = new Dept();
dept.setdId(1);
dept.setdName("cat");
System.out.println(dept);
String asString = MAPPER.writeValueAsString(dept);
System.out.println(asString);
}
//2、把json字符串转成java对象(反序列化)
@Test
public void tojava() throws IOException {
String json = "{\"dId\":1,\"dName\":\"cat\"}";
Dept dept = MAPPER.readValue(json, Dept.class); //单个json串
System.out.println(dept);
}
//3、解析京东价格json串,获取某个商品的价格
@Test
public void getPrice() throws Exception{
String json = "[{\"cbf\":\"0\",\"id\":\"J_100000287121\",\"m\":\"15000.00\",\"op\":\"4299.00\",\"p\":\"4299.00\"}]";
//1、json特点:数组,第一条记录,从这个记录当中获取key=p的值
//利用api获取这个数组
JsonNode jsonNode = MAPPER.readTree(json);
//获取第一条记录
JsonNode jsonNode1 = jsonNode.get(0);
//获取记录里面的key为P的值
JsonNode s = jsonNode1.get("p");
double v = s.asDouble();
System.out.println(v);
}
}
简单爬取:
public class TestJsoup {
/**
* 利用Jsoup爬取页面标题信息
* 1、创建链接
* 2、获取页面
* 3、根据classID筛选信息
*/
@Test
public void getInfo() throws Exception {
String url = "http://zhaojiu.hgnu.edu.cn/";
//建立连接,相当于创建socket对象
Connection connection = Jsoup.connect(url);
//获取页面
Document document = connection.get();
//利用select选择器,从页面中获取指定标签内容,返回的是数组
Elements select = document.select(".news_title");
for (Element e : select) {
System.out.println(e.text());
}
}
//爬取商品价格
/**
* JsonNode可以是
* 对象: {"a":"1", "b":"2"}
* 数组: [{...}, {...}, {...}]
* isArray() 判断是否是一个数组
* get(i) 取数组中指定下标的节点
* get(name) 取对象中该属性的值
* @throws Exception
*/
@Test
public void getPrice() throws Exception {
String url = "https://p.3.cn/prices/mgets?skuIds=100000287121";
String userAgent = "Mozilla/5.0 (Windows NT 5.1; zh-CN) AppleWebKit/535.12 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/535.12";
//拿到json串的内容
String json = Jsoup.connect(url).userAgent(userAgent).ignoreContentType(true).execute().body();
//解析
//创建ObjectMapping对象
ObjectMapper om = new ObjectMapper();
//拿到数组
JsonNode jsonNode = om.readTree(json);
//拿到数组里面的第一条数据
JsonNode jsonNode1 = jsonNode.get(0);
//拿出指定key的value
double p = jsonNode1.get("p").asDouble();
System.out.println(p);
}
}
5. 解析.properties文件
开发步骤:
- 定位这个文件
- 创建一个文件流(FileInputStream)
- 利用Properties prop 创建属性文件对象
- prop.load(fis)读取
- 打印prop展现所有内容
@Test
public void testProp() throws IOException {
//获取当前项目的字节码输出的根路径
String path = this.getClass().getResource("/").getPath();
String p = path + "/javase/resources/jdbc.properties";
//创建文件流对象
FileInputStream fis = new FileInputStream(p);
//创建Properties对象
Properties prop = new Properties();
prop.load(fis);
System.out.println(prop);
String property = prop.getProperty("jdbc.psw");
System.out.println(property);
fis.close();
}
6. 解析xml文件
解析xml文件(以Mybatis的mapper.xml映射文件为例),利用dom4j工具类
- 把里面的SQL语句解析出来
- 根据id去找到对应SQL语句
开发步骤:- 导入dom4j工具包
- 定位到当前类所在目录,然后得到mapper.xml映射文件
- 创建解析对象SAXReader
- 获取根元素
- 获取里面的第一级元素
- 遍历数组打印出所有属性
- 获取标签的内容
@Test
public void testDom4j() throws Exception{
String id = "findAll";
//获取文件路径
String path = this.getClass().getResource("").getPath() + "/Mapper.xml";
//创建SAXReader对象
SAXReader reader = new SAXReader();
FileInputStream fis = new FileInputStream(path);
//获取文档内容
Document document = reader.read(fis);
//获取根元素内容
Element rootElement = document.getRootElement();
//获取根元素的属性值
Attribute namespace = rootElement.attribute("namespace");
System.out.println(namespace.getValue());
//获取根元素下级内容
Iterator<Element> iterator = rootElement.elementIterator();
while (iterator.hasNext()) {
//获取子元素
Element next = iterator.next();
//遍历属性
Iterator<Attribute> iterator1 = next.attributeIterator();
while (iterator1.hasNext()) {
Attribute next1 = iterator1.next();
if (id.equals(next1.getValue())) {
System.out.println("id为"+id+"的内容:"+next.getStringValue().trim());
}
}
}
}
7. 类的单例设计
package com.java.oop.instance;
/**
* 面试:谈谈 你对单例模式的认识?
* 对象单例模式:设计类时保证类的实例在内存中只有一份
* 1、内部设计实现:对类自身进行设计
* 2、外部设计实现:对类的对象提供一种池(spring的bean池)
*/
//如何保证如下类的设计在内存中只有一份类的实例
/**
* 线程安全,有阻塞、少阻塞
* 适合大对象,稀少用(并发访问少)
*/
class Singleton02 {
/*
volatile关键字的作用
1、保证线程的可见性:
2、禁止指令重排序
3、但不能保证其原子性
*/
//当多个线程对一个共享变量进行操作时,用volatile修饰保证线程可见性,禁止指令重排序
private static volatile Singleton02 instance = null;
//构造方法私有化,不允许外界直接构建对象
private Singleton02() {
System.out.println("Singleton02()");
}
/**
* 线程不安全
* 1、多个线程并发执行
* 2、多个线程由共享数据集
* 3、多个线程在共享数据集上的操作是非原子操作
*/
//synchronize保证代码的原子性(不能同时有多个线程妒对这个代码块进行访问)
//synchronize要让多个线程在这个代码块上顺序执行
//此设计虽然保证了安全,但性能会被降低
/*public synchronized static Singleton02 getInstance() {
if (instance == null) {
instance = new Singleton02();
}
return instance;
}*/
//重构如上方法的设计,即要保证安全又要提高性能
public static Singleton02 getInstance() {
if (instance == null) {
synchronized (Singleton02.class) {
System.out.println("synchronized");
if ((instance == null)){
instance = new Singleton02(); //分配空间,属性初始化,调用构造方法,为instance复赋值
}
}
}
return instance;
}
}
/**
* 方案3:线程安全,无阻塞
* 缺陷:可能占用资源比较多,尤其是大对象
* 适合小对象,频繁访问
*/
class Singleton03 {
private Singleton03() {}
//类加载时被创建且只创建一次
private static Singleton03 instance = new Singleton03();
public static Singleton03 getInstance() {
return instance;
}
public static void show() {}
}
/**
* 单例设计方案4
* 适合大对象,频繁用(高并发,大量访问),没有阻塞
*/
class Singleton04 {
private Singleton04() {}
static class Inner{
//使用内部类实现属性的延时初始化(延迟加载)
private static Singleton04 instance = new Singleton04();
}
public static Singleton04 getInstance() {
return Inner.instance;
}
//public static void show() {}
}
public class ObjectInstanceTest03 {
public static void main(String[] args) {
doTestManyThread02();
}
private static void doTestManyThread02() {
//局部内部类
class Task implements Runnable {
@Override
public void run() {
Singleton02.getInstance();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread thread1 = new Thread(new Task());
Thread thread2 = new Thread(new Task());
Thread thread3 = new Thread(new Task());
thread1.start();
thread2.start();
thread3.start();
}
private static void doTestSingleThread01() {
Singleton02 i1 = Singleton02.getInstance();
Singleton02 i2 = Singleton02.getInstance();
//判断是否为统一对象
if (i2 == i1) {
System.out.println("单例");
} else System.out.println("多例");
}
}
8. java四种引用方式
package com.java.oop.instance;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
class Member {
int id;
String name;
public Member(int id,String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Member{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalize()");
}
}
//-Xmx5m -Xms5m -XX:PrintGCDetails
public class ObjectInstanceTest02 {
public static void main(String[] args) {
//强引用(不会被回收)
/*Member m1 = new Member(10, "A");
m1 = null;*/
//1、弱引用
//1)、弱引用对象(只要触发了GC,引用的对象就会被回收)
//WeakReference<Member> wr = new WeakReference<>(new Member(20, "B"));
//2)、使用弱引用引用的对象
//System.out.println(wr.get());
//2、软引用(SoftReference)
//1)软引用对象(内存不足时,软引用引用的对象会被回收)
//SoftReference<Member> sr = new SoftReference<>(new Member(30, "C"));
//2)使用软引用引用的对象
//System.out.println(sr.get());
//3、虚引用(记录被回收的对象)
//1)虚引用对象
ReferenceQueue rq = new ReferenceQueue();
PhantomReference<Member> pr = new PhantomReference<>(new Member(40, "D"), rq);
System.out.println(pr.get());
byte[] a1 = new byte[1024*1024];
byte[] a2 = new byte[1024*1024];
byte[] a3 = new byte[1024*1024];
byte[] a4 = new byte[1024*1024];
//System.gc()*
}
}
具体参考:
https://juejin.im/post/6844903665241686029链接
9. 利用linkedHashMap简单实现LRU
package com.java.oop.features;
import java.util.LinkedHashMap;
import java.util.Map;
//自定义LRUCache对象
class LruCache extends LinkedHashMap<String,Object> {
private int maxCap;
LruCache(int maxCap) {
super(6,0.75f,true);
this.maxCap = maxCap;
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
return size() > maxCap;
}
}
public class LruCacheTest01 {
public static void main(String[] args) {
//doTestLinkedHashMap01();
LruCache lruCache = new LruCache(3);
lruCache.put("A",11);
lruCache.put("B",22);
lruCache.put("C",33);
lruCache.put("D",44);
lruCache.get("C");
System.out.println(lruCache);
}
private static void doTestLinkedHashMap01() {
/*
LinkedHashMap
1、数据结构:链表+散列表
2、算法:记录元素添加顺序,记录元素访问顺序
*/
LinkedHashMap<String,Integer> linkedHashMap = new LinkedHashMap<String,Integer>(
3, //初始容量
0.75f, //加载因子
false //false表示记录添加顺序,ture记录访问顺序
) {
/**
* 每次执行put都会执行该方法;方法返回true就会移除不经常访问的元素 eldest
* @param eldest
* @return
*/
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() >= 3;
}
};
linkedHashMap.put("A", 22);
linkedHashMap.put("B", 23);
linkedHashMap.put("C", 232);
linkedHashMap.put("D", 3232);
linkedHashMap.get("B");
System.out.println(linkedHashMap);
}
}
Mybatis不使用xml配置文件链接数据库
public class BaseWithoutXmlTest {
protected SqlSessionFactory factory;
//Mybatis 不使用配置文件进行数据操作
@Before
public void init() throws SQLException {
//第三方数据库连接池Hikari
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/jtsys?useUnicode=true&characterEncoding=utf8&useSSL=false");
ds.setUsername("root");
ds.setPassword("123456");
//构建事务工厂
TransactionFactory transactionFactory = new JdbcTransactionFactory();
//构建环境对象
Environment environment = new Environment("development",transactionFactory,ds);
//构建Configuration对象
Configuration configuration = new Configuration(environment);
//构建SQLSessionFactory
factory = new SqlSessionFactoryBuilder().build(configuration);
}
@Test
public void testSSF() {
System.out.println(factory);
SqlSession sqlSession = factory.openSession();
Connection connection = sqlSession.getConnection();
System.out.println(connection);
}