目录
Java整理笔记
Day2-12-15
基于并发模型测试——多线程测试5个人获取5个链接userThread
验证是否存在线程安全的资源抢占问题
多线程——线程的创建、锁、并发关键字JVM
web——Http协议
生产者——消费者模型
通过带参的构造方法可以让代码块里的同类方法共享一个对象,如多线程共享一个池子;
synchronized 锁、锁块(可以用于局部块上锁)
synchronized(….){ }
lock 锁,必须解锁
lock.lock() lock.unlock()【用try-finally承接,使unlock()必须执行】
获取有限资源——等待并重复性获取连接
重复连接——计数器(控制等待时间)int count = 50; if(count =50) break;
有限资源连接——上锁等待的同时仍需要在一定时间内进行重复的获取
Pools 连接池
repeategetConnection()
getInstance()返回一个Pools
经过第一阶段分析:
- package com.kim.sql;
- import java.sql.Connection;
- import java.util.ArrayList;
- /*
- * Function:连接池
- * 1 池子创建
- * 2 给池子装入连接对象
- * 3 将池子中的连接对象分配给用户
- * 3.1 如何分配?
- * ——>顺序扫描,扫描得到可用的Connection, 已被占用 true 未被占用false
- * ——>占用一个连接的同时将它的标志位标为true
- *
- * */
- public class Pools {
- ArrayList<CreatePoolsConnection> poolLists[邓1] ;
- int num = 5;
- //给池子中装入连接
- {
- poolLists = new ArrayList<CreatePoolsConnection>();
- //实现静态块装入
- for(int i=0;i<num;i++) {
- //装入专门构造的CreatePoolsConnection对象
- poolLists.add(new CreatePoolsConnection());
- }
- }
- //将池子里的连接进行分配
- public Connection getPoolsConnection() {
- //用标志位衡量判断连接是否被占用
- Connection conn = null;
- for(CreatePoolsConnection pl:poolLists) {
- if(!pl.isUsed[邓2] ()) {
- // 找到闲置的poolConnection,将它分配给poolconn
- conn = pl.getConn();
- pl.setUsed(true);
- break;
- }
- }
- return conn;
- }
- public static void main(String arg[])
- {
- Pools pl = new Pools();
- // for(int i=0;i<pl.num;i++) {
- // System.out.println("Connections--------" +pl.poolLists.get(i));
- // }
- for(CreatePoolsConnection plconn:pl.poolLists) {
- System.out.println(plconn.getConn()+((plconn.isUsed())?"已用":"未被占用"));
- }
- }
- }
CreatepoolsConnection 装入的连接
分配连接:每个连接(可用性标识,名称【方便测试】)
并发测试连接获取:
UserThread
run()
{
释放连接,便于下一个用户使用;
}
Pools
repeategetConnection()
{
repeategetConnection()
}
UserThread
单例模式:(保证大家用的为同一个类的实例)(底层源码常用控制方法)
在外部不能new , 外部统一使用一个对象
实现方法:懒汉式、饿汉式、枚举、双重检验锁
例子:
————课设中保证大家用同一个池子——————
方案:让这个池子在外设中不能直接new,而通过内部方法提供,即只能在内部new一次,这样就能保证是同一个池子
如何使构造方法不能new?————构造方法私有化————private ClassName(){}
饿汉式:(一上来就New一个)
publc pools[邓3] {
static Pools pl = new Pools[邓4] ();
private Pools(){//构造方法私有化,使得想获取该对象不能直接new 而是需要通过方法获得
}
public static Pools getInstance(){return pl;}//获取创建好的池子的对象
}
Pools pools = Pools.getInstance();
for(int i=0;i<6;i++) {
new userThread(pools,"线程"+(i+1)).start();
}
懒汉式:需要时再new——在get方法中new
单例模式例子——详细
多态中的动态绑定技术——子类绑定父类方法
CreatePoolsConnection
createStatement()——运行的是implement后的类的方法
解决:
public static Statement createStatement(){
//此处有疑问
//surper createStatement();
conn. createStatement();
}
当前时间函数:long timw = system.currentTimeMillis();
优化:
- 将必须内容放入配制文件;
- 优化用户访问的算法;
Day3-12-16
连接池自定义;
JDBC结构的封装
JDBC--------基础
步骤:
- 注册驱动
- 创建连接
- 创建执行对象
- 将sql语句送入执行对象进行执行
- 利用执行结果
资源释放
反射
异常
DriverManager源码
如何优化select * 查询——索引
ResultSet的底层数据结构?如何存储结果集?
方法的重载
Mybits
Eclispse : Control + F 快速查找关键词
execute——executeUpdate、executeQuery
对数据库连接、增、删改查进行封装,得到工具类打包成jar——JDBCUtils
传统的JDBC弊端:
- 手动获取连接——》冗余
- 进行增删改查的操作一致 executeUpdate(sql)
- 只是sql 语句不同——》没必要为每一种操作都提供一种方法
单条记录查询、全表查询
- 优化:
- 快速的获取连接——自定义池子
- 提供一个唯一的更新方法(提高开发效率)——》JDBC的结构封装
- JDBC封装
4.1
数组的初始化:
动态初始化, new——》没有值;
静态初始化,不需要new——》直接给值;
预处理,通过方法进行参数匹配
(今天任务)
存储参数
Object[] values = {null,”66”,”232”,”544”};
待处理
Strings sql = “insert into user01 values(?,?,?,?) ”;
采用预处理方式进行绑定:存储参数——》待处理
PrepareStatement:半成品的sql;——》预处理(可以解决SQL入注问题)——》必须经过加工补全,才能正常执行;
PrepareStatement pst = conn. prepareStatement(sql);
pst.setInt(1,参数数组);
pst.setObject(2,null);——》setObject啥都能传——》可以用它来传null
Statement:完整的sql;
Day4-12-17
- 利用预处理,将增删改放置一个方法中;
利用静态数组存储待Update的values
- 进行单元测试;
轮询调度算法
单元测试
@Test(import org.junit.jupiter.api.Test;)
1) @ 是注解
2) @Test注解是JUnit测试的基础,它提供了其他作用;JUnit 4的优势就在于支持了注解。
@Test的使用:
是该方法可以不用main方法调用就可以测试出运行结果,是一种测试方法一般函数都需要有main方法调用才能执行,注意被测试的方法必须是public修饰的;
RowMapper ——》 用来完成对结果集的处理
RowMapper(ResultSet rs)
- //单值查询——》解决代码重用率高的问题
- public void queryForObject(String sql,Object[] values) {
- //进行预处理,通过setObject()方法实现赋值,增加其实用性和通用性
- try {
- pst = conn.prepareStatement(sql);
- for(int i=0;i<values.length;i++) {
- pst.setObject(i+1,values[i]);
- }
- rs = pst.executeQuery();
- if(rs.next()) {
- int id = rs.getInt("id");
- String username = rs.getString[邓5] ("username");
- String password = rs.getString("password");
- System.out.println(id+"\t"+username+"\t"+password);
- }
- } catch (SQLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
Day5-12-18
获取数据库的查询结果
从数据库查询得到的数据——》需求:转化成为对象——》便于前端或者需要时使用
方法:创建响应的类 如 User类——》提供一个无参的构造方法 ——》通过JavaBean(setter 和getter) 进行数据存储
(控制台查看结果快捷方式:source里的toString——》构造打印方法,打印对象里的全部属性)
结果:查询的结果一对象的形式存在;
System.out.println(user);
打印出地址原因:user调用了Object 的 toString方法
故我们重写toString()方法后就可以直接通过 System.out.println(user); 输出了;
多态、继承、接口
抽象类和接口的区别?——书P147;
接口只提供一种行为规范,不需要加具体的值
通过多态处理结果集
进行封装时最好别放一个具体的类,而是放一个接口,便于灵活应变;
如下面,创建接口 RowMapper 和两个子类 UserMapper 、 TeacherMapper
多态:一对多
//queryForObject(sql,values,new RowMapper())
queryForObject(sql,values,new UserMapper())
queryForObject(sql,values,new TeacherMapper())
最终方法返回为 承接对象(如user),里面包含查询结果
List集合:ArrayList和List的区别
Map集合
多变参数:
public void queryForObject(Stirng sql, RowMapper rowMapper,object… values)
反射
聊原理、聊底层——优化
反射机制可以用来对类进行操作:
- 获取类本身的信息 类的全路径 父类
- 类的方法的信息
- 类的构造方法
- 类的私有方法
- 类的某个方法
- 类的属性
Person类——》被反射机制反射的类
ByReflectDealPerson类——》通过反射机制处理Person的类
- 创建该类的运行时类的Class
@Before
这里的代码会在所以的测试代码之前被执行——》通常搭配@Test
A Field
提供有关类或接口的单个字段的信息和动态访问。 反射的字段可以是类(静态)字段或实例字段。
Day6-12-21
基本数据类型、引用数据类型;
反射机制管理set、get方法
set和get方法需要分别的创建两个方法进行管理;
内部代码构建(set为例子):
- 找到set方法 ——》 能够执行set方法 ——》将需要的参数传递进去
- getMethod()【getMethod(String name, Class...<?> parameterTypes)】
——》 invoke() 【invoke(Object obj, Object... args)】
- 将运行时类通过参数传入——》动态性【Class clazz】
- 获取set方法 Method method = clazz.getMethod(“setUsername”,String.class);
- 通过set、get方法分别进行存值和取值;
动态性——》getMethod(String name, Class...<?> parameterTypes)中的name进行动态获取
动态的获取set/get方法
手动的拼接出:一个set方法,用来动态的获取set方法的名字;
set + 属性首字母大写 + 剩下的字符串
属性首字母大写:subString(0,1).toUpperCase();
剩下的字符串: subString(1)
setMethodName = “set”+ str.subString(0,1).toUpperCase()+str.subString(1);
比如对对象User 的 username 获取set方法:
str = “username”;
setMethodName = “set”+str.subString(0,1).toUpperCase()+ str.subString(1);
数据类型:
基本数据类型:char 、int、float等;
引用数据类型:String、自定义类型等;
反射的动态性:
可以将类名放入配制文件中,便于操作改变;
反射动态处理结果集:
rs.setInt(age);
获取属性——》Filed——》拿到所有的属性
得到属性的类型,并进行匹配从而进行下一步操作
age.getType().getName().equals(“int”);
反射机制动态处理ResultSe:
反射机制动态处理ResultSet——》将结果集转换为对象进行存储——》反射机制动态的写一个能够将查询出来的记录自动转换为对象进行存储;
拿到结果集 rs ——》转换为对象进行存储 user = new User(); user.setUsername(username)
——》动态获取(将代码写活),不能出现直接的set、get方法;
fields得到结果集中的所有属性;
遍历所有的属性;
传入任意个 :三个点
JAVA中“...”三个点:可变长参数,就是这个位置可以传入任意个该类型参数,简单来说就是个数组长度灵活可变的数组;
学生管理系统项目
crud——》增查改删 (creat, retrieve, update, delete);
WebContent——》动态、静态资源文件
Day7-12-22
SpringMVC框架
执行删除:
doDelet.jsp:
执行删除;——DeletByIdDao(Object…values)
跳转到查询页面;
执行新增:
代码写完后进行定点测试;
—————————————————————————————————————————
执行修改:
dao:DAO(Data Access Object) 数据访问对象
学生管理系统设计:
今天课上,实现了 展示所有学生信息记录 、 删除学生信息记录 、 修改学生信息记录;
展示所有学生信息记录:
userInfoShow.jsp——》通过JSP中嵌入Java代码进行查询,并使用表格方法显示;
- <%=userList.get(i).getId()%></td>
删除学生信息记录:
过程描述:在展示页面上选择某学生后面的删除键从而删除该生记录;
实际代码运行过程:一次删除——》一次查询——》再次跳转到展示全页面;
doDeleteById.jsp——》通过JSP中嵌入Java代码进行删除,并返回显示全部内容;
- doDeleteById.doDeleteById(values);
修改学生信息记录:
过程描述:在展示页面上选择某学生后面的修改键从而修改该生记录;
实际代码运行过程:一次update——》一次查询——》再次跳转到展示全页面;
doUpdateByID.jsp——》通过JSP中嵌入Java代码进行修改,并返回显示全部内容;
- Object[] values = {username,password,age1,id1};
- doUpdateById.doUpdateById(values);
实现动态读取配制文件——ServletConfig
Day9-12-24
SpringMVC的核心模型——Servlet
servlet——》运行在服务器端的程序
servlet——》响应用户端的请求
实现Servlet implements Servlet ——》 配制Servlt(在配制文件中进行配制)
配制Servlt(在配制文件中进行配制)——》利用了反射
interface Servlet:httpServlet、genericServlet
用继承代替实现——》减少耦合
get和post
get——》没有请求体,参数暴露在地址栏
post——》有请求体,参数藏在服务器内部
servlet的三个阶段:
- init出生——最先被执行,只执行一次;
- service运行——请求多少次就运行多少次;
- destroy摧毁——服务器关闭时运行一次;
protected void doGet(xxx) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
protected void doPostxxx) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
在post中调用get,提高复用性——》避免了不同请求方式,相同的处理解决方式;
注解代替xml配制——》
封装servlet
三个作用——》取、调、跳
取——》取值;
调——》调用 其他java类 执行逻辑;
跳——》跳转到新的页面;
JSTL——在JSP中快捷取值;
-
- request.getRequestDispacher(“url”).forword(request,response);
- response.sendRedirect()
执行逻辑例子:
修改:
servlet进行查询——》jsp进行显示——》jsp提交修改内容——》Servlet进行修改——》servlet进行查询——》jsp进行显示;
传统servlet的缺点:
-
-
- 每一次都需要继承HttpServlet;
- 配制臃肿;
-
基于反射机制进行Servlet优化:
作用:为SpringMVC源码学习打下基础;
使用封装好的Servlet:
-
-
-
- .properties配置文件解析;
- 集合的合理使用;
-
-
配制臃肿
减少servlet的数量—— 一个servlet干原有多的servlet的事;
一个servlet——》增删改查(单条查,全查)——》将它们封装在servlet的5个方法中
如何让servlet中的5个方法执行?
具体处理请求的5个方法全都依靠 Get 方法;
在doGet方法中执行 那5个具体的方法:
通过if——else判断具体执行哪个方法——》判断条件——》客户端请求时带上请求方法名
——》新的问题:多层的嵌套判断效率非常低
解决方案——》利用反射 Method = getDeclaredMethod(String name, Class...<?> parameterTypes)
invoke(Object obj, Object... args)执行方法;——》替代臃肿的if-else判断;
methodName ——》从客户端读取 action=”FatherServlet?methodName=delect&id=1”——》可以用&进行连接从而传递多个参数——只能在POST下通过URL传递参数
前者弊端:
-
-
-
-
- 更改了servlet原有的格式——只有post和get方法;
- FatherServlet固化;
-
-
-
优化 2.0:
更改了servlet原有的格式——只有post和get方法
创建一个新的java普通类——》将原来servlet中的5个方法拿出;
将类的全路径放在配置文件中——》利用反射在Servlet中执行外部类的方法;
在fatherServlet中解析proties配制文件——》获取到类的全路径——》Class.forName(“url”);
用Map存储 取到的 key—value 键值对——》通过for循环将键值对信息都存在Map中;
Class.forName(classFlag.get(methodName))——》methodName通过URL请求参数传过来;
前者弊端:
- 更改了servlet原有的格式——只有post和get方法;
- FatherServlet固化;
动态显示配制 配置文件的 路径
request.getRealPath(filename):获取当前文件的完整路径;
将filename放入web.xml中;
通过webconfig读取配置文件中值;——》servlet中的Init(Config)方法——》config.getInitParamiter();
两部分:
-
- 加载配制信息——Map存储;
- 利用反射动态执行方法;