Java入门第一季
1.JAVA标识符注意事项:
(1)JAVA标识符可以由字母、数字、下划线(_)、美元符($)组成,但不能包含@、%、空格等其它特殊字符,不能以数字开头。
(2)标识符不能是Java关键字和保留字(Java预留的关键字,以后的升级版本中有可能作为关键字),但可以包含关键字和保留字。
(3)标识符是严格区分大小写的。
(4)标识符的命名最好能反映出其作用,做到见名知意。
2.Java中的数据类型
在Java的领域里,基本数据类型变量存的是数据本身,而引用类型变量存的是数据的空间地址。
3.Java语言中常用的运算符:
算术运算符、赋值运算符、比较运算符、逻辑运算符、条件运算符。
4.使用Arrays类操作Java中的数组:
- 排序
语法:Arrays.sort(数组名);
- 将数组转换为字符串
语法:Arrays.toString(数组名);
Java入门第二季
1.类
类是模子,确定对象将会拥有的特征(属性)和行为(方法)。
类的特点:
类是对象的类型
具有相同属性和方法的一组对象的集合。
2.使用对象的步骤:
- 创建对象:
类名 对象名 = new 类名();
Telphone phone = new Telphone();
- 使用对象:
引用对象的属性:对象名.属性
Phone.screen =5;
引用对象的方法:对象名.方法名();
Phone.sendMessage();
3.成员变量和局部变量
- 成员变量
在类中定义,用来描述对象将要有什么。
- 局部变量
在类的方法中定义,在方法中临时保存数据。
成员变量和局部变量区别:
(1)作用域不同
局部变量的作用域仅限于定义它的方法。
成员变量的作用域在整个类内部都是可见的。
(2)初始值不同
Java会给成员变量一个初始值,Java不会给局部变量赋予初始值
(3)在同一个方法中,不允许有同名局部变量;在不同的方法中,可以有同名局部变量。
(4)两类变量同名时,局部变量具有更高的优先级。
4.构造方法
(1)使用new + 构造方法 创建一个新的对象。
(2)构造方法是定义在Java类中的一个用来初始化对象的方法。
(3)构造方法与类同名且没有返回值。
(4)当没有指定构造方法时,系统会自动添加无参的构造方法。
(5)当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法。
(6)构造方法的重载:方法名相同,但参数不同的多个方法,调用时会自动根据不同的参数选择相应的方法。
(7)构造方法不但可以给对象的属性赋值,还可以保证给对象的属性赋一个合理的值。
5.Java中的static使用之静态变量注意事项:
(1)静态成员属于整个类,当系统第一次使用该类时,就会为其分配内存空间直到该类被卸载才会进行资源回收!
(2)静态方法中可以直接调用同类中的静态成员,但不能直接使用调用非静态成员。(如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。)
(3)在普通成员方法中,则可以直接访问同类的非静态变量和静态变量。
6.Java中的static使用之静态初始化块注意事项:
静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。(使用static修饰初始化块,成为静态初始化块)
- 封装
7.1封装概念及好处
- 概念:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
- 好处:
- 只能通过规定的方法访问数据。
- 隐藏类的实例细节,方便修改和实现。
7.2Java中的包
- 包的作用:
管理Java文件,解决同名文件冲突。
- 定义包:package包名
注:必须放在Java源程序的第一行,包名间可以使用“.”号隔开.
- 系统中的包
Java.(功能).(类)
Java.lang.(类) 包含java语言基础的类。
Java.util(类) 包含java语言中的各种工具类。
Java.io.(类) 包含输入、输出相关功能的类。
- 包的使用
- 可以通过import关键字,在某个文件使用其它文件中的类。
- Java中,包的命名规范是全小写字母拼写。
使用的时候不但可以加载某个包下的所有文件(eg:com.imooc.*),也可以加载某个具体子包下的所有文件(eg:com.imooc.music)。
7.3 java中的访问修饰符
访问修饰符 | 本类 | 同包 | 子类 | 其他 |
private | √ |
|
|
|
默认 | √ | √ |
|
|
protected | √ | √ | √ |
|
public | √ | √ | √ | √ |
7.4.java中的this关键字
(1)this关键字代表当前对象
this.属性 操作当前对象的属性
this.方法 调用当前对象的方法
(2)封装对象的属性的时候,经常会使用this关键字。
7.5 java中的内部类
内部类(Inner Class)就是定义在另外一个类里面的类。
作用:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
- 内部类的方法可以直接访问外部类的所有数据,包括私有的数据。
- 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。
内部类可分为以下几种:
※成员内部类
※静态内部类
※方法内部类:就是内部类定义在外部类的方法中,方法内部类只在该方法的内容可见,即只在该方法内可以使用。
※匿名内部类
成员内部类的使用方法:
- Inner类定义在Outer类的内部,相当于Outer类的一个成员变量的位置,Inner类可以使用任意访问控制符,如public、protected、private等。
- Inner类中定义的test()方法可以直接访问Outer类中的数据,而不受访问控制符的影响,如直接访问Outer类中的私有属性。
- 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去new一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类();
- 内部类的.class文件总是这样:外部类名$内部类名.class
静态内部类就是static修饰的内部类,这种内部类的特点是:
- 静态内部类不能直接访问外部类的非静态成员,但可以通过new 外部类().成员的方式访问。
- 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员。
- 创建 静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名 = new 内部类();
方法内部类注意事项:
由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和static修饰符。
- 继承
8.1继承的初始化顺序
(1)初始化父类再初始子类。
(2)先执行初始化对象中的属性,再执行构造方法中的初始化。
8.2 Java中的super的使用
Super关键字:
在对象的内部使用,可以代表父类对象。
- 访问父类的属性
Super.age
- 访问父类的方法
Super.eat()
Super的应用
子类的构造的过程中必须调用其父类的构造方法。(隐式调用)。
如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。(super关键字)
如果显示的调用构造方法,必须在子类的构造方法的第一行。例如:
Public Dog(){
Super();
System.out.println(“ddd”);
}
如果子类构造方法中既没有显式调用父类的构造方法,而父类又没有无参的构造方法,则编译出错。
8.3 Java中的Object类
Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object类。
Object类中的方法,适合所有子类。
(1)toString()方法
在Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串)。
可以通过重写toString()方法表示出对象的属性。
(2)equals()方法
比较的是对象的引用是否指向同一块内存地址。
Dog dog = new Dog();
一般情况下比较两个对象时比较他的值是否一致,所以要进行重写。
- 多态
9.1 多态:对象的多种形态
- 引用多态
父类的引用可以指向本类的对象
父类的引用可以指向子类的对象
- 方法多态
创建本类对象时,调用的方法为本类方法
创建子类对象时,调用的方法为子类重写的方法或者继承的方法
9.2 引用类型转换
(1)向上类型转换(隐式/自动类型转换),是小类型到大类型的转换。
(2)向下类型转换(强制类型转换),是大类型到小类型的转换。
(3)instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题。(用于判断一个引用是否是某个类型或某个类型的子类型)
Dog dog = new Dog();
Animal animal = dog;//向上类型转换 自动类型转换
Dog dog2 = (Dog)animal;
If(animal instanceof Cat){
Cat cat = (Cat)animal;//1.编译时Cat类型 2.运行时Dog类型
}else{
System.out.println(“无法进行类型转换”);
}
9.3 抽象类
(1)概念:抽象类前使用abstract关键字修饰,则该类为抽象类。
(2)应用场景:
a、在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。
b、从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。
(3)作用:
限制规定子类必须实现某些方法,但不关注实现细节。
(4)使用规则:
a、abstract定义抽象类
b、abstract定义抽象方法,只有声明,不需要实现
c、包含抽象方法的类是抽象类
d、抽象类中可以包含普通的方法,也可以没有抽象方法
e、抽象类不能直接创建,可以定义引用变量
9.4 接口
(1)接口概念
类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。(接口就是用来被继承、被实现的,修饰符一般建议用public.注意:不能使用private和protected修饰接口)
(2)接口定义
和类定义不同,定义接口不再使用class关键字,而是使用interface关键字。
常量:
接口中的属性是常量,即使定义时不添加public static final 修饰符,系统也会自动加上。
方法:
接口中的方法只能是抽象方法,总是使用,即使定义时不添加public abstract修饰符,系统也会自动加上。
- 使用接口
一个类可以实现一个或多个接口,实现接口使用implements关键字。Java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充。
继承父类实现接口的语法为:
[修饰符]class 类名 extends 父类implements接口1,接口2...
{
类体部分//如果继承了抽象类,需要实现继承的抽象方法;
}
如果要继承父类,继承父类必须在实现接口之前。
9.5 UML
(1)用例图(The Use Case Diagram)
用例图能够以可视化的方式,表达系统如何满足所收集的业务规则,以及特定的用户需求等信息。
(2)序列图(The Sequence Diagram)
序列图用于按照交互发生的一系列顺序,显示对象之间的这些交互。
(3)类图(The Class Diagram)
UML类图、业务逻辑和所有支持结构一同被用于定义全部的代码结构。
Java入门第三季
1.异常与异常处理
1.1 Java异常简介
有异于常态,和正常情况不一样,有错误出现。
阻止当前方法或作用域,称之为异常。
1.2 实际应用中的经验与总结
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定
- 尽量添加finally语句块去释放占用的资源
- Java中的字符串
2.1 “==”和equals()区别
- ==:判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象。
- equals():比较存储在两个字符串对象中的内容是否一致。
- Java中必须了解的常用类
3.1 基本类型和包装类之间的对应关系
基本类型 | 对应的包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
3.2 装箱和拆箱
装箱:把基本类型转换成包装类,使其具有对象的性质,又可分为手动装箱和自动装箱。
int i = 10;//定义一个int基本类型值
Integer x = new Integer(i);//手动装箱
Integer y = i;//自动装箱
拆箱:和装箱相反,把包装类对象转换成基本类型的值,又可分为手动拆箱和自动拆箱。
Integer j = new Integer(8);//定义一个Integer包装类对象,值为8
int m = j.intValue();//手动拆箱为int类型
Int n = j;//自动拆箱为int 类型
3.3 基本数据类型和字符串直接转换
- 基本类型转换为字符串有三种方法:
- 使用包装类toString()方法
- 使用String类的valueOf()方法
- 用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串。
例子:
//将基本类型转换为字符串
int c = 10;
String str1 = Integer.toString(c);//方法一
String str2 = String.valueOf(c);//方法二
String str3 = c + “”;//方法三
- 将字符串转换成基本类型有两种方法:
- 调用包装类parseXxx静态方法
- 调用包装类valueOf()方法转换为基本类型的包装类,会自动拆箱
例子:
//将字符串转换为基本类型
String str = “8”;
Int d = Integer.parseInt(str);//方法一
Int e = Integer.valueOf(str);//方法二
3.4 SimpleDateFormat类使用
可以使用java.text包中的SimpleDateFormat类来对日期时间进行格式化,可以将日期转换为指定格式的文本,也可将文本转换为日期。
- 使用format()方法将日期转换为指定格式的文本
例子:
//创建Data对象,表示当前时间
Date d = new Date();
//创建SimpleDateFormat对象,指定目标格式
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
//调用format方法,格式时间,转换为指定格式字符串
String today = sdf.format(d);
//输出转换后的字符串
System.out.println(today);
- 使用parse()方法将文本转换为日期
例子:
//创建日期格式的字符串
String day = “2014年02月14日10:30:25”;
//创建SimpleDateFormat对象,指定字符串的日期格式
SimpleDateFormat df = new SimpleDateFormat(“yyyy年MM月dd日HH:mm:ss”);
//调用parse()方法,将字符串转换为日期
Date date = df.parse(day);
//输出转换后的时间
System.out.println(“当前时间:”+date);
注意:
- 调用SimpleDateFormat对象的parse()方法时可能会出现转换异常,即ParseException,因此需要进行异常处理。
- 使用Date类时需要导入java.util包,使用SimpleDateFormat时需要导入java.text包。
3.5 Calendar类的应用
Java.util.Calendar类是一个抽象类,可以通过调用getInstance()静态方法获取一个Calendar对象,此对此已由当前日期时间初始化,即默认代表当前时间,如Calendar c = Calendar.getInstance();
例子:
Calendar c = Calendar.getInstance();//创建Calendar对象
int year = c.get(Calendar.YEAR);//获取年
int month = c.get(Calendar.MONTH) + 1;
- Java中的集合框架
4.1 Collection接口
- 是List、Set和Queue接口的父接口
- 定义了可用于操作List、Set和Queue的方法--增删改查
4.2 List接口及其实现类--ArrayList
- List是元素有序并且可以重复的集合,被称为序列
- List可以精确的控制每个元素的插入位置,或删除某个位置元素
- ArrayList---数组序列,是List的一个重要实现类
- ArrayList底层是由数组实现的。
4.3 泛型
集合中的元素,可以是任意类型的对象(对象的引用),如果把某个对象放入集合,则会忽略他的类型,而把他当做Object处理
泛型则是规定了某个集合只可以存放特定类型的对象(会在编译其对类型进行检查,可以直接按指定类型获取集合元素,泛型结合可以添加泛型的子类型的对象实例,泛型结合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错!)
泛型集合中的限定类型不能使用基本数据类型,可以通过使用包装类限定允许存入的基本数据类型。
4.4 Set接口及其实现类---HashSet
(1)Set是元素无序并且不可以重复的集合,被称为集。
(2)HashSet--哈希集,是Set的一个重要实现类。
4.5 Map接口
Map提供了一种映射关系,其中的元素是以键值对(key -value)的形式存储的,能够实现根据key快速查找value。
Map中的键值对以Entry类型的对象实例形式存在。
键(key值)不可重复,value值可以
每个键最多只能映射到一个值
Map支持泛型,形式如:Map<K,V>
4.6 HashMap类
HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现。
HashMap中的Entry对象是无序排列的
Key值和value值都可以为null,但是一个HashMap只能有一个key值为null的映射(key值不可以重复)。
4.7 Comparable接口--可比较的
实现该接口表示:这个类的实例可以比较大小,可以进行自然排序。
定义了默认的比较规则
其实现类需实现compareTo()方法
compareTo()方法返回正数表示大,负数表示小,0表示相等
4.8 Comparator接口--比较工具接口
用于定义临时比较规则,而不是默认比较规则
其实现类需要实现compare()方法
Comparator和Comparable都是Java集合框架的成员
JAVA遇见HTML---Servlet篇
- Servlet
Servlet是在服务器上运行的小程序,一个Servlet就是一个Java类,并且可以通过“请求-响应”编程模型来访问的这个驻留在服务器内存里的Servlet程序。
1.1 Tomcat容器等级
Tomcat的容器分为四个等级,Servlet的容器管理Context容器,一个Context对应一个Web工程。
1.2 编写Servlet步骤
- 继承HttpServlet
- 重写doGet()或者doPost()方法
- 在web.xml中注册Servlet
1.3 Get方式请求HelloServlet
1.4 Servlet生命周期
- 初始化阶段,调用init()方法
- 响应客户请求阶段,调用service()方法。由service()方法根据提交方式选择执行doGet()或者doPost()方法。
- 终止阶段,调用destroy()方法。
1.5 Tomcat装载Servlet的三种情况
在下列时刻Servlet容器装载Servlet:
- Servlet容器启动时自动装载某些Servlet,实现它只需要在web.xml文件中的<Servlet></Servlet>之间添加如下代码:<loadon-startup>1</loadon-startup>数字越小表示优先级别越高。
- 在Servlet容器启动后,客户首次向Servlet发送请求。
- Servlet类文件被更新后,重新装载Servlet。
- Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。
1.6 Servlet与九大内置对象
JSP对象 | 怎样获得 |
out | resp.getWriter |
request | service方法中的req参数 |
response | Service方法中的resp参数 |
session | req.getSession()函数 |
application | getServletContext()函数 |
exception | Throwable |
page | this |
pageContext | PageContext |
Config | getServletConfig函数 |
1.7 Servlet路径跳转
(1)请求重定向方式跳转到test.jsp,当前路径是ServletPathDirection/servlet,而test.jsp在项目根目录下,则:
response.sendRedirect(request.getContextPath()+”/test.jsp”);
其中使用request.getContextPath获得上下文对象。
- 使用服务器内部跳转(“/”代表根目录或者“../”)
request.getRequestDispatcher("/test.jsp").forward(request, response);
- 应用MVC架构实现项目
2.1 Model1简介(JSP+JavaBean)
2.2 Model2简介(Java Web的Model2开发模型就是MVC思想的体现。)
JAVA遇见HTML--JSP篇
- JAVA WEB简介
1.1 Tomcat服务器的目录结构
目录 | 说明 |
/bin | 存放各种平台下用于启动和停止Tomcat的命令文件 |
/conf | 存放Tomcat服务器的各种配置文件 |
/lib | 存放Tomcat服务器所需的各种JAR文件 |
/logs | 存放Tomcat的日志文件 |
/temp | Tomcat运行时用于存放临时文件 |
/webapps | 当发布Web应用时,默认会将Web应用的文件发布于此目录中 |
/work | Tomcat把由JSP生成的Servlet放于此目录下 |
1.2 WEB-INF目录结构
- WEB-INF是Java的WEB应用的安全目录。所谓安全就是客户端无法访问,只有服务端可以访问的目录。
- Web.xml,项目部署文件。
- Classes文件夹,用以放置*.class文件。
- Lib文件夹,用于存放需要的jar包。
1.3 修改Tomcat服务器默认端口
修改conf/server.xml文件
- JSP基础语法
2.1 JSP简介
JSP全名为Java Server Pages,其根本是一个简化的Servlet设计,他实现了在Java当中使用HTML标签。Jsp是一种动态网页技术标准也是JAVAEE的标准。JSP与Servlet一样,是在服务器端执行的。
2.2 JSP页面元素构成:
JSP页面组成部分包括:指令、表达式、小脚本、声明、注释、静态内容。
JSP指令:
- Page指令:通常位于jsp页面的顶端,同一个页面可以有多个page指令。
- Include指令:将一个外部文件嵌入到当前JSP文件中,同时解析这个页面中的JSP语句。
- Tablib指令:使用标签库定义新的自定义标签,在JSP页面中启用定制行为。
2.3 JSP指令之page指令
Page指令语法:
<%@page 属性1=”属性值” 属性2=”属性值1,属性值2”...
属性n=”属性值n”%>
属性 | 描述 | 默认值 |
language | 指定JSP页面使用的脚本语言 | java |
import | 通过该属性来引用脚本语言中使用到的类文件 | 无 |
contentType | 用来指定JSP页面所采用的编码方式 | Text/html,ISO-8859-1 |
2.4 JSP注释
在JSP页面的注释。
HTML的注释:
<!--html注释--> //客户端可见
JSP的注释:
<%--html注释--%> //客户端不可见
JSP脚本注释:
//单行注释
/**/多行注释
2.5 JSP脚本
在JSP页面中执行的java代码。
语法:
<% Java代码%>
2.6 JSP声明
在JSP页面中定义变量或者方法。
语法:
<%! Java代码%>
2.7 JSP表达式
在JSP页面中执行的表达式。
语法:
<%= 表达式 %> //注意:表达式不以分好结束
2.8 JSP页面声明周期
其中jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同事请求该JSP文件,则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多个线程方式执行可以大大降低对系统的资源需求,提高系统的并发量及响应时间。但也要注意多线程的编程带来的同步问题,由于该Servlet始终驻留内存,所以响应是非常快的。
- JSP内置对象(上)
3.1 内置对象简介
JSP内置对象是Web容器创建的一组对象,不使用new关键字就可以使用的内置对象。
常用的九大JSP内置对象:
Out、request、response、session、application、page、pageContext、exception、config
3.2 Out对象
Out对象是JspWriter类的实例,是向客户端输出内容常用的对象。
常用方法如下:
- void println()向客户端打印字符串
- void clear()清除缓冲区的内容,如果在flush之后调用会抛出异常。
- Void clearBuffer();清除缓冲区的内容,如果在flush之后调用不会抛出异常。
- void flush()将缓冲区内容输出到客户端
- int getBufferSize() 返回缓冲区以字节数的大小,如不设缓冲区则为0
- int getRemaining()返回缓冲区还剩余多少可用
- boolean isAutoFlush()返回缓冲区满时,是自动清空还是抛出异常
- Void close()关闭输出流。
3.3 get与post区别
<from name = “regForm” action =”动作” method=”提交方式”></form>
表单有两种提交方式:get与post
- get:以明文的方式通过URL提交数据,数据在URL中可以看到。提交的数据最多不超过2KB。安全性较低但效率比post方式高。适合提交数据量不大,安全性不高的数据。比如:搜索、查询等功能。
- Post:将用户提交的信息封装在HTML HEADER内。适合提交数据量大,安全性高的用户信息。比如:注册、修改、上传等功能。
3.4 request对象
客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。Request对象具有请求域,即完成客户端的请求之前,该对象一直有效。常用方法如下:
- String getParameter(String name)返回name指定参数的参数值
- String []getParameterValues(String name)返回包含参数name的所有值的数组
- Void setAttribute(String name);存储此请求中的属性
- Object getAttribute(String name)返回指定属性的属性值
- String getContentType()得到请求体的MIME类型
- String getProtocol()返回请求用的协议类型及版本号
- String getServerName()返回接受请求的服务器主机名
- Int getServerPort()返回服务器接受此请求所用的端口号
- String getCharacterEncoding()返回字符编码方式
- Void setCharacterEncoding()设置请求的字符编码方式
- Int getContentLength()返回请求体的长度(以字节数)
- String getRemoteAddr()返回发送此请求的客户端IP地址
- String getRealPath(String path) 返回一虚拟路径的真实路径
- String request.getContextPath() 返回上下文路径
3.5 response对象
response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。Response对象具有页面作用域,即访问一个页面时,该页面内的response对象只能对这次访问有效,其他页面的response对象对当前页面无效。常用方法如下:
- String getCharacterEncoding()返回响应用的是何种字符编码
- void setContentType(String type)设置响应的MIME类型
- PrintWriter getWriter() 返回可以向客户端输出字符的一个对象(注意比较:PrintWriter与内置out对象的区别,输出总是提前与内置out对象)
- sendRedirect(java.lang.String location)重新定向客户端的请求。
3.6 请求转发与请求重定向区别
- 请求重定向:客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次的请求对象不会保存,地址栏的URL地址会改变。
- 请求转发:服务器行为,request.getRequestDispatcher().forward(req,resp);是一次请求,转发后请求对象会保存,地址栏的URL地址不会改变。
- JSP内置对象(下)
4.1什么是session
- session表示客户端与服务器的一次会话。
- Web中的session指的是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。
- 从上述定义中可以看到,session实际上是一个特定的时间概念
4.2 session对象
- session对象是一个JSP内置对象。
- Session对象在第一个JSP页面被装载时自动创建,完成会话期管理。
- 从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。
- 当一个客户访问一个服务器时,可能会在服务器的几个页面之间切换,服务器应当通过某种办法知道这个一个客户,就需要session对象。
- Session对象是HttpSession类的实例。
4.3 session对象常用方法如下:
- long getCreationTime():返回session创建时间。
- pulibc String getId():返回session创建时JSP引擎为它设的唯一ID号
- public Object setAttribute(String name,Object value):使用指定名称将对象绑定到此会话。
- Public Object getAttribute(String name): 返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下,则返回null.
- String []getValueNames():返回一个包含此session种所有可用属性的数组。
- Int getMaxInactiveInterval():返回两次请求间隔多长时间此seesion被取消(单位秒)。
4.4 session的声明周期
- 创建:
当客户端第一次访问某个jsp或者servlet时候,服务器会为当前会话创建一个sessionId,每次客户端向服务端发送请求时,都会将此sessionId携带过去,服务端会对此sessionId进行校验。
- 活动:
某次会话当中通过超链接打开的新页面属于同一次会话。
只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
除非本次会话的所有页面都关闭后再重新访问某个JSP或者servlet将会创建新的会话。
注意事项:注意原有会话还存在,只是这个旧的sessionId仍然存在于服务端,只不过再也没有客户端会携带它然后交予服务端校验。
- 销毁:
Seesion的销毁只有三种方式:
※ 调用了session.invalidate()方法。
※ session过期(超时)
※ 服务器重新启动
※ Tomcat 默认session超时时间为30分钟。
※ 设置session超时有两种方式:
- session.setMaxInactiveInterval(时间);//单位是秒
- 在web.xml配置
<session-config><session-timeout>10</session-timeout></session-config>//单位是分钟。
4.5 application对象
(1)application对象实现了用户间数据的共享,可存放全局变量。
(2)application开始于服务器的启动,终止于服务器的关闭。
(3)在用户的前后连接或不同用户之间的连接中,可以对application对象的同一属性进行操作。
(4)在任何地方对application对象属性的操作,都将影响到其他用户对此的访问。
(5)服务器的启动和关闭决定了application对象的生命。
(6)application对象是ServletContext类的实例。
4.6 application对象常用方法如下:
(1)public void setAttribute(String name,Object value)使用指定名称将对象绑定到此会话。
(2)public Object getAttribute(String name)返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下,则返回null.
(3)Enumeration getAttributeNames()返回所有可用属性名的枚举。
(4)String getServerInfo()返回JSP(SERVLET)引擎名及版本号。
4.7 page对象
Page对象就是指向当前JSP页面本身,有点像类中的this指针,它是java.lang.Object类的实例。常用方法如下:
- class getClass()返回此Object的类。
- Int hasCode()返回此Object的hash码
- boolean equals(Object obj)判断此Object是否与指定的Object对象相等。
- void copy(Object obj)把此Object拷贝到指定的Object对象中
- Object clone()克隆此Object对象
- String toString()把此Object对象转换成String类的对象
- void notify()唤醒一个等待的线程
- void notifyAll()唤醒所有等待的线程
- void wait(int timeout)使一个线程处于等待直到timeout结束或被唤醒。
- void wait()使一个线程处于等待直到被唤醒。
4.8 pageContext对象
·pageContext对象提供了对JSP页面内所有的对象及名字空间的访问
·pageContext对象可以访问到本页所在的session,也可以取本页面所在的application的某一属性值
·pageContext对象相当于页面中所有功能的集大成者
·pageContext对象的本类名也叫pageContext.
常用方法如下:
- JspWriter getOut() 返回当前客户端响应被使用的JspWriter流(out)
- HttpSession getSession()返回当前页中的HttpSession对象(session)
- Object getPage()返回当前页的Object对象(page)
- ServletRequest getRequest()返回当前页的ServletRequest对象(request)
- ServletResponse getResponse()返回当前页的ServletResponse对象(response)
- void setAttribute(String name,Object attribute)设置属性及属性值
- Object getAttribute(String name,int scope)在指定范围内取属性的值
- int getAttributeScope(String name)返回某属性的作用范围
- void forward(String relativeUrlPath)使当前页面重导到另一页面
- void include(String relativeUrlPath)在当前位置包含另一文件
4.9 Config对象
Config对象是在一个Servlet初始化是,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象),常用方法如下:
- ServletContext getServletContext() 返回含有服务器相关信息的ServletContext对象。
- String getInitParameter(String name) 返回初始化参数的值
- Enumeration getInitParameterNames() 返回Servlet初始化所需所有参数的枚举。
4.10 Exception对象
Exception对象是一个异常对象,当一个页面在运行过程中发生了异常,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象,常用方法如下:
- String getMessage() 返回错误异常的消息
- String toString()返回关于异常的简短描述消息
- Void printStackTrace() 显示异常及其栈轨迹
- Throwable FillInStackTrace()重写异常的执行栈轨迹
- JavaBeans
Javabeans就是符合某种特定的规范的Java类。使用Javabeans的好处是解决代码重复编写,减少代码冗余,功能区分明确,提高了代码的维护性。
5.1 Javabean的设计原则
公有类、无参的公有构造方法、属性私有、getter和setter方法。
例如:
//设计学生类
public class Students{
private String name;
private int age;
public Students(){}
public void setName(String name){this.name=name;}
Public String getName(){return this.name;}
public void setAge(int age){this.age=age;}
public int getAge(){return this.age;}
}
5.2 什么是Jsp动作
JSP动作元素(action elements),动作元素为请求处理阶段提供信息。动作元素遵循XML元素的语法,有一个包含元素名的开始标签,可以有属性、可选的内容、与开始标签匹配的结束标签。主要包含以下五类
第一类是与存取JavaBean有关的,包括:
<jsp:useBean><jsp:setProperty><jsp:getProperty>
第二类JSP1.2就开始有的基本元素,包括6个动作元素
<jsp:include><jsp:forward><jsp:param><jsp:plugin><jsp:params><jsp:fallback>
第三类是JSP2.0新增加的元素,主要与JSP Document有关,包括六个元素
<jsp:root><jsp:declaration><jsp:scriptlet><jsp:expression><jsp:text><jsp:output>
第四类是JSP2.0新增的动作元素,主要用来动态生成XML元素标签的值,包括3个动作<jsp:attribute><jsp:body><jsp:element>
第五类是JSP2.0新增的动作元素,主要是用在Tag File中,有2个元素
<jsp:invoke><jsp:dobody>
5.3 在JSP页面中如何使用Javabeans
(1)像使用普通java类一样,创建javabean实例。
(2)在jsp页面中通常使用jsp动作标签使用javabean.
其中:
※ <jsp:useBeans>作用:在JSP页面中实例化或者在指定范围内使用javabean:
<jsp:useBean id=”标识符” class=”java类名” scope=”作用范围”/>
※ <jsp:setProperty>作用:给已经实例化的Javabean对象的属性赋值,一共有四种形式。
<jsp:setProperty name=”JavaBean实例名” property=”*”/>(跟表单关联)
<jsp:setProperty name=”JavaBean实例名” property=”JavaBean属性名”/>(跟表单关联)
<jsp:setProperty name=”JavaBean实例名” property=”JavaBean属性名” value=”BeanValue”/>(手工设置)
<jsp:setProperty name =”JavaBean实例名” property =”propertyName” param=”request对象中的参数名”/>(跟request参数关联)
※ <jsp:getProperty>作用:获取指定Javabean对象的属性值
<jsp:getProperty name=”JavaBean实例名” property=”属性名”/>
5.4 Javabean的四个作用域范围
说明:使用useBeans的scope属性可以用来指定javabean的作用范围。
· page//仅在当前页面有效
· request//可以通过HttpRequest.getAttribute()方法取得JavaBean对象
· session //可以通过HttpSession.getAttribute()方法取得JavaBean对象。
· application //可以通过application.getAttribute()方法取得Javabean对象。
5.5 Model1简介
- JSP状态管理
6.1 http协议的无状态性
无状态是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚才那个浏览器。
简单地说,就是服务器不会去记得你,所以就是无状态协议。
保存用户的状态的两大机制:Session、Cookie
6.2 Cookie概述
(1)什么是cookie?
Cookie:中文名称为“小甜饼”,是web服务器保存在客户端的一系列文本信息。
典型应用一:判定注册用户是否已经登录网站。
典型应用二:“购物车”的处理。
(2)Cookie的作用
· 对特定对象的追踪
· 保存用户网页浏览记录与习惯
· 简化登录
安全风险:容易泄露用户信息。
(3)JSP中创建与使用Cookie
常用方法:
方法名称 | 说明 |
void setMaxAge(int expiry) | 设置cookie的有效期,以秒为单位 |
void setValue(String value) | 在cookie创建后,对cookie进行赋值 |
String getName() | 获取cookie的名称 |
String getValue() | 获取cookie的值 |
int getMaxAge() | 获取cookie的有效时间,以秒为单位 |
(4)Session与Cookie对比
session | cookie |
在服务器端保存用户信息 | 在客户端保存用户信息 |
Session中保存的是Object类型 | Cookie保存的是String类型 |
随会话的结束而将其存储的数据销毁 | Cookie可以长期保存在客户端 |
保存重要的信息 | 保存不重要的用户信息 |
- JSP指令与动作元素
7.1 include指令
语法:
<%@ include file=”URL”%>
7.2 include动作(动作标签)
语法:
<jsp:include page=”URL” flush=”true|false”/>其中:page:要包含的页面,flush:被包含的页面是否从缓冲区读取。
7.3 include指令与include动作的区别
| Include指令 | jsp:include动作 |
语法格式 | <%@ include file=”..” %> | <jsp:include page=”..”> |
发生作用的时间 | 页面转换期间 | 请求期间 |
包含的内容 | 文件的实际内容 | 页面的输出 |
转换成的Servlet | 主页面和包含页面转换一个Servlet | 主页面和包含页面转换为独立的Servlet |
编译时间 | 较慢--资源必须被解析 | 较快 |
执行时间 | 稍快 | 较慢--每次资源必须被解析 |
7.4 forward动作
语法:
<jsp:forward page=”URL”/>
等同于:
Request.getRequestDispatcher(“/url”).forward(request,response);
7.5 param动作
语法:
<jsp:param name=”参数名” value=”参数值”>
常常与<jsp:forward>一起使用,作为其的子标签。
深入浅出Java多线程
- Java多线程基础概念介绍
1.1 进程
程序(任务)的执行过程,持有资源(共享内存,共享文件)和线程。
1.2 线程
线程是系统在洪最小的执行单元,同一进程有多个线程。线程共享进程的资源。
- Java线程初体验
2.1 Thread常用方法
类别 | 方法签名 |
|
线程的创建 | Thread() |
|
Thread(String name) |
| |
Thread(Runnable target) |
| |
Thread(Runnable target,String name) |
| |
线程的方法 | void start() | 启动线程 |
static void sleep(long millis) | 线程休眠 | |
static void sleep(long millis,int nanos) | ||
void join() | 使其他线程等待当前线程终止 | |
void join(long millis) | ||
void join(long millis,int nanos) | ||
static void yield() | 当前运行线程释放处理器资源 | |
获取线程引用 | static Thread currentThread() | 返回当前运行的线程引用 |
- 使用进程注意事项
- 停止线程不要使用stop()、interrupt()方法,使用退出标志停止线程。
- 使用volatile保证了线程可以正确的读取其他线程写入的值。(volatile boolean keepRunning = true;)
- 线程交互
4.1 争用条件
当多个线程同时共享访问同一数据(内存区域)时,每个线程都尝试操作该数据,从而导致数据被破坏,这种线程称为争用条件。
4.2 互斥与同步
相交进程之间的关系主要有两种,同步与互斥。所谓互斥,是指散步在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其他进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。所谓同步,是指散步在不同进程之间的若干程序片段,他们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。
显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。
也就是说互斥是两个线程之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个才能运行,而同步也是不能同时运行,但他是必须要安照某种次序来运行相应的线程(也是一种互斥)!
总结:互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。
互斥的实现:synchronized(intrinsic lock)
同步的实现:wait()/notify()/notifyAll() 都是object对象而非Thread类
反射--Java高级开发必须懂的
- Class类的使用
1.1 Class类
- 在面向对象的世界里,万事万物皆对象。基本的数据类型(void关键字什么的)都存在类类型。
类是对象,类是java.lang.Class类的实例对象。(任何一个类都是Class的实例对象,这个实例对象有三种表示方式)
例子:Dog dog1 = new Dog();
//第一种表示方式--->实际在告诉我们任何一个类都有一个隐含的静态成员变量class. Class c1 = Dog.class;
//第二种表达方式 已经知道该类的对象通过getClass方法
Class c2 = dog1 .getClass();
//官网 c1,c2表示了Dog类的类类型(class type)
//第三种表达方式
Class c3 = null;
c3 = Class.forName(“com.imooc.reflect.Dog”);
//我们可以通过类的类类型创建该类的对象实例-->通过c1 or c2 or c3创建Dog的类类型。Dog dog = (Dog)c1.newInstance();//需要有无参数的构造方法
- Java动态加载类
new 创建对象 是静态加载类,在编译时刻就需要加载所有的可能用到的类。通过动态加载类可以解决该问题。
动态加载类,在运行时刻加载
示例代码:
(1)public class OfficeBetter {
public static void main(String[] args) {
try {
//动态加载类,在运行时刻加载
//Class c = Class.forName("com.immoc.reflect.Word");
Class c = Class.forName(args[0]);
//通过类类型,创建该类对象
OfficeAble oa = (OfficeAble)c.newInstance();
oa.start();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
(2)public interface OfficeAble {
public void start();
}
(3)public class Word implements OfficeAble{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("word.....start");
}
}
(4)public class Excel implements OfficeAble{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("Excel.....start");
}
}
- 方法的反射
- 如何获取某个方法
方法的名称和方法的参数列表才能唯一决定某个方法。
- 方法反射的操作
Method.invoke(对象,参数列表)
- 通过Class,Method来认识泛型的本质
反射的操作都是编译之后的操作
如下代码示例:
ArrayList list = new ArrayList();
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1==c2);//true
其中,c1==c2结果返回true 说明编译之后集合的泛型是去泛型化的。Java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了。我们可以通过方法的反射来绕过编译。
如下代码示例:
try {
Method m = c2.getMethod("add", Object.class);
m.invoke(list1, 20);
System.out.println(list1.size());
System.out.println(list1);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
文件传输基础--Java IO流
- 文件的编码
- GBK编码中文占用2个字节,英文占用1个字节
- UTF-8编码中文占用3个字节,英文占用1个字节。
- JAVA是双字节编码utf-16be,utf-16be 中文占用2个字节,
- File常用API介绍
(1)Java.io.File类用于表示文件(目录)
File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问。 (2)RandomAcessFile java提供的对文件内容的访问,既可以读文件,也可以写文件。RandomAcessFile支持随机访问文件,可以访问文件的任意位置。
- Java文件模型:在硬盘上的文件是 byte byte byte存储的,是数据的集合。
- 打开文件:有两种模式”rw”(读写)”r”(只读)
RandomAccessFile raf = new RandomAccessFile(file,”rw”);文件指针,打开文件时指针在开头pointer = 0;
- 写方法
raf.write(int)--->只写一个字节(后8位),同事指针指向下一个字节位置,准备再次写入。
- 读方法
int b = raf.read() --->读一个字节
- 文件读写完成以后一定要关闭(Oracle官方说明)。
- 字节流
3.1 InputStream、OutputStream
InputStream抽象了应用程序读取数据的方式,OutputStream抽象了应用程序写出数据的方式。
3.2 EOF = End 读到-1就读到结尾
3.3 输入流基本方法
//把文件作为字节流进行读操作
FileInputStream in = new FileInputStream(fileName);
int b = in.read();读取一个字节无符号填充到int低八位。-1是EOF
in.read(byte[]buf);读取数据填充到字节数组buf
In.read(byte[]buf,int start,int size);读取数据到字节数组buf,从buf的start位置开始存放size长度的数据。
3.4 输出流基本方法
//如果该文件不存在,则直接创建,如果存在,删除后创建
FileOutputStream out = new FileOutputStream(“demo/out.data”);
out.write(int b);写出一个byte到流,b的低8位
out.write(byte[] buf)将buf字节数组写入到流
out.write(byte []buf,int start,int size);字节数组buf从start位置开始写size长度的字节到流。
3.5 FileInputStream- ->具体实现了在文件上读取数据
3.6 FileOutputStream 实现了向文件中写出byte数据的方法
3.7 字节流之数据输入输出流
DataOutputStream/DataInputStram 对”流’功能的扩展,可以更加封边的读取int,long,字符等类型数据。对于DataOutputStream而言有writeInt()/writeDouble()/writeUTF()
3.8 BufferedInputStream&BufferedOutputStream
这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。从应用程序中把输入放入文件,相当于将一缸水倒入到另一缸水。
FileOutputStream --->write()方法相当于一滴一滴的把水“转移”过去。
DataOutputStream --->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去。
BufferedOutputStream --->write方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入另一缸中。
- 字符流
4.1 认识文本和文本文件
Java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)。
文件是byte byte byte...的数据序列
文本文件是文本(char)序列按照某种编码方案(utf-8、utf-16be,gbk)序列为byte的存储结果。
4.2 字符流(Read Writer)操作的是文本、文本文件。
字符的处理,一次处理一个字符
字符的底层仍然是基本的字符序列。
字符流的基本实现:
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWriter 提供char流到byte流,按照编码处理。
4.3 FileReader/FileWriter
4.4 字符流的过滤器
BufferedReader --->readLine 一次读一行
BufferedWriter/PrintWriter --->写一行
- 对象的序列化和反序列化
- 对象的序列化,就是将Object转换成byte序列,反之叫对象的反序列化。
- 序列化流(ObjectOutputStream),是过滤流---writeObject
反序列化流(ObjectInputStream)---readObject - 序列化接口(Serializable)
对象必须实现序列化接口才能进行序列化,否则将出现异常。这个接口没有任何方法,只是一个标准。 - transient:对象属性加上transient关键字后不会进行jvm默认的序列化,也可以自己完成这个元素的序列化。writeObject、readObject方法可参看ArrayList源码
序列化参考代码:
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化
s.writeInt(stuage);//自己完成stuage的序列化
}
反序列化参考代码:
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException,ClassNotFoundException{
s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作t
this.stuage = s.readInt();//自己完成stuage的反序列化操作
}
- 序列化中子类和父类构造函数的调用问题
一个类实现了序列化接口,那么其子类都可以进行序列化。
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用。
二进制基础
- 二进制位运算
运算符 | 运算 | 示例 |
& | 与运算 | 6 & 3 = 2 |
| | 或运算 | 6 | 3 = 7 |
^ | 异或运算 | 6 ^ 3 = 5 |
~ | 反码 | ~6 = -7 |
<< | 左移 | 3 << 2 = 12 3*2*2 = 12 |
>> | 右移 | 3 >> 1 = 1 3/2 = 1 |
>>> | 无符号右移 | 3 >>> 1 = 1 3/2 = 1 |
2.Java内置的进制转换
十进制转成十六进制 | Integer.toHexString(int i) |
十进制转成八进制 | Integer.toOctalString(int i) |
十进制转成二进制 | Integer.toBinaryString(int i) |
十六进制转成十进制 | Integer.valueOf(“FFFF”,16).toString() |
八进制转成十进制 | Integer.valueOf(“376”,8).toString() |
二进制转成十进制 | Integer.valueOf(“0101”,2).toString() |
JDBC之“对岸的女孩看过来”
- JDBC简介
JDBC全称 Java Data Base Connectivity(java 数据库连接)可以为多种数据库提供统一的访问,体现了java “编写一次,处处运行”的高大上精神。
- JDBC使用详解
2.1 JDBC编程步骤
- 加载驱动程序:Class.forName(driverClass);
加载Mysql驱动:Class.forName(“com.mysql.jdbc.Driver”);
加载Oracle驱动:Class.forName(“oracle.jdbc.driver.OracleDriver”);
- 获得数据库连接:
DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/imooc”,”root”,”root”);
- 创建Statement对象:conn.createStatement();
- JDBC各种连接方式的对比
- JDBC + ODBC桥的方式
特点:需要数据库的ODBC驱动,仅适用于微软的系统。
- JDBC + 厂商API的形式
特点:厂商API一般使用C编写。
- JDBC + 厂商Database Connection Server + DataBase的形式
特点:在JAVA与DATABASE之间架起了一台专门用于数据库连接的服务器(一般由数据库厂商提供)。
- JDBC + DATABASE的连接方式
特点:这使得Application与数据库分开,开发者只需关心内部逻辑的实现而不需注重数据库连接的具体实现。(推荐使用)
JDBC之“对岸的女孩走过来”
- JDBC详解之存储过程的调用
1.1 JDBC调用无参存储过程
(1)存储过程代码:
CREATE PROCEDURE imooc_db.sp_select_nofillter()
BEGIN
Select * from imooc_goddess;
END;
- 调用代码:
Connection conn = DBUtil.getConnection();
CallableStatement c = conn.prepareCall(“call sp_select_nofilter()”);
c.execute();
ResultSet rs = c.getResultSet();
1.2 JDBC调用带输入参数的存储过程
- 存储过程代码:
CREATE DEFINER=’imooc’@’localhost’ PROCEDURE ‘sp_select_filter’(IN sp_name VARCHAR(20))
BEGIN
IF sp_name IS NULL OR sp_name = ‘’ THEN
SELECT * FROM imoo_goddess;
ELSE
IF length(sp_name)=11 AND substring(sp_name,1,1)=1 THEN
SELECT * FROM imooc_goddess WHERE mobile=sp_name;
ELSE
SELECT * FROM imooc_goddess WHERE user_name LIKE concat(‘%’,sp_name,’%’);
END IF;
END IF;
END
- 调用代码:
//1.获得连接
Connection conn = DBUtil.getConnection();
//2.获得callablestatement
CallableStatement cs = conn.prepareCall(“call sp_select_filter(?)”);
cs.setString(1,sp_name);
//3.执行存储过程
cs.execute();
//处理结果集:结果集,出参
ResutSet rs = cs.getResultSet();
1.3 JDBC调用带输出参数的存储过程
- 存储过程代码:
CREATE DEFINER = ‘imooc’@’localhost’PROCEDURE ‘sp_select_count’(OUT count INT(10))
BEGIN
SELECT count(*) INTO count FROM imooc_goddess;
END
- 调用代码:
//1.获得连接
Connection conn = DBUtil.getConnection();
//2.获得callablestatement
CallableStatement cs = conn.prepareCall(“call sp_select_count(?)”);
cs.registerOutParameter(1,Types.INTEGER);
//3.执行存储过程
cs.execute();
//处理返回的记过:结果集,出参
cs.getInt(1);
- JDBC详解之事务处理
2.1 事务的概念和特点
事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作。这些操作作为一个整体向系统提交,要么都执行、要么都不执行。
- 原子性(Atomicity):事务是一个完整的操作。
- 一致性(Consistency):当事务完成时,数据必须处于一致状态。
- 隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的。
- 永久性(Durability):事务完成后,它对数据库的修改被永久保持。
2.2 JDBC对事务管理的支持
- 我们通过提交commit()或是回退rollback()来管理事务的操作。
- 事务操作默认是自动提交。
- 可以通过调用setAutoCommit(false)来禁止自动提交。
- JDBC升级之连接池
3.1 常用的开源数据库连接池
- dbcp
- c3p0
3.2 dbcp 与c3p0区别
dpcp | C3p0 |
Spring组织推荐使用 | Hibernate组织推荐使用 |
强制关闭连接或者数据库重启后,无法自动重连 | 强制关闭连接或者数据库重启后,可以自动重连。 |
没有自动的去回收空闲连接的功能 | 自动回收空闲连接功能 |
DBCP有着比C3P0更高的效率,可能出现丢失连接。 | C3P0稳定性较高 |
DBCP提供最大连接数 | C3P0提供最大空闲时间 |
DBCP并没有相应的功能 | C3P0可以控制数据源内加载的PreparedStatements数量,并且可以设置帮助线程的数量来提升JDBC操作的速度。 |
- JDBC升级之替代产品
4.1 Hibernate简介
优点:
- 轻量级的ORM框架。
- 对JDBC进行了很好的封装,使用了ORM做了映射,那么就可以通过面向对象的方式很容易的操作数据库了。
- 它还提供了缓存机制,可以提高效率。
缺点:
如果对大量的数据库进行频繁的操作,性能效率比较低,不如直使用JDBC。
4.2 Hibernate核心接口
- Session接口:Session接口负责执行持久化对象的CRUD操作。
- SessionFactory接口:SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。
- Configuration接口:Configuration接口负责配置启动Hibernate,创建SessionFactory对象。
- Transaction接口:Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。
- Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。
4.3 MyBatis简介
特点:
- 易于上手和掌握。
- sql写在xml里,便于统一管理和优化。
- 解除sql与程序代码的耦合。
- 提供映射标签,支持对象与数据库的orm字段关系映射。
- 提供对象关系映射标签,支持对象关系组建维护。
- 提供xml标签,支持编写动态sql。
Java高并发之魂:Synchronized深度解析
- Synchronized简介
1.1 Synchronized的作用
能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。
1.2 Synchronized的两个用法
(1)对象锁:包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)。
其中同步代码块锁示例:
/**
* 对象示例1,代码块形式
*/
public class SynchronizedObjectCodeBlock2 implements Runnable{
static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
Object lock = new Object();
@Override
public void run() {
synchronized (lock){
System.out.println("我是对象锁的代码块形式。我叫"
+Thread.currentThread().getName());
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行结束");
}
}
public static void main(String args[]){
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()){
}
System.out.println("finished");
}
}
方法锁示例:
/**
* 对象锁实例2,方法锁形式
*/
public class SynchronizeObjectMethod3 implements Runnable{
static SynchronizeObjectMethod3 instance = new SynchronizeObjectMethod3();
public static void main(String args[]){
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()){
}
System.out.println("finished");
}
@Override
public void run() {
method();
}
public synchronized void method(){
System.out.println("我的对象锁的方法修饰符形式,我叫"
+Thread.currentThread().getName());
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
(1)类锁:指synchronized修饰静态的方法或指定锁为Class对象。
类锁概念:Java类可能有很多个对象,但只有一个Class对象。
只有一个Class对象:Java类可能会有很多个对象,但是只有一个Class对象。
本质:所以所谓的类锁,不过是Class对象的锁而已。
用法和效果:类锁只能在同一时刻被一个对象拥有。
类锁两种形式:
形式1:synchronized加在static方法上。
示例:
public static synchronized void method(){
System.out.println("我的对象锁的方法修饰符形式,我叫"
+Thread.currentThread().getName());
try {
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
形式2:synchronized(*.class)代码块。
示例:
private void method(){
synchronized (SynchronizedClassClass5.class){
System.out.println("我是类锁的第二种形式"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("该线程执行关闭:"+Thread.currentThread().getName());
}
}
- 多线程访问同步方法核心思想
- 一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应第1、 5中情况)
- 每个实例都对应有自己的一把锁,不同实例之间互不影响;例外:锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象共用同一把类锁(对应第2、 3、 4、 6种情况)。
- 无论是方法正常执行完毕或者方法抛出异常,都会释放锁(对应第7种情况)。
- Synchronized的性质
3.1 性质1:可重入
什么是可重入:指的是同一线程的外层函数获得锁之后,内层函数可以直接再次获取该锁。
好处:避免死锁、提升封装性。
粒度:线程而非调用。
3.2 性质2:不可中断
一旦这个锁已经被别人获得了,如果我还想获得,我只能选择等待或者阻塞,直到别的线程释放这个锁。如果别人永远不释放锁,那么我只能永远地等待下去。
相比之下,未来会介绍的Lock类,可以拥有中断的能力,第一点,如果我觉得我等的时间太长了,有权中断现在已经获取到锁的线程的执行;第二点,如果我觉得我等待的时间太长了不想再等了,也可以退出。
- 深入原理
4.1 加锁和释放的原理
深入JVM看字节码,使用javap -verbose *.class 来反编译字节码,使用monitorenter与monitorexit指令来进行加锁与释放锁。
4.2 可重入原理:加锁次数计数器
JVM负责跟踪对象被加锁的次数。
线程第一次给对象加锁的时候,计数变为1。每当这个相同的线程在此对象上在此获得锁时,计数会递增。
每当任务离开时,计数递减,当计数为0的时候,锁被完全释放。
4.3 可见性原理:JAVA内存模型
4.4 Synchronized缺陷
- 效率低:锁的释放情况少、试图获得锁时不能设定超时、不能中断一个正在试图获得锁的线程。
- 不够灵活(读写锁更灵活):加锁和释放锁的时机单一,每个锁仅有单一的条件(某个对象),可能是不够的
- 无法知道是否成功获取到锁。
- 常见问题
- synchronized关键字使用注意点:锁对象不能为空、作用域不宜过大、避免死锁。
- 有现成的包就用,如果适用优先使用synchronized关键字。
- 多线程访问同步方法的七种具体情况
- 两个线程访问的是一个对象的同一个同步方法。
- 两个线程访问的是两个实例的同一个同步方法。
- 两个线程访问的是synchronized的静态方法。
- 同时访问同步方法与非同步方法。
- 访问同一个对象的不同的普通同步方法。
- 同时访问静态synchronized和非静态synchronized方法
- 方法抛异常后,会释放锁。
JSP常用标签
- JSTL简介
JSTL是java中的一个定制标记库集,它实现了JSP页面中的代码复用(基于标签库原理,重复率较高的代码支持复用,提高效率),书写JSP页面时可读性强。注意:JSTL标签和Server及JSP页面有着比较严格的版本对应关系,版本对应不正确很容易抛出异常。
环境搭建:新建web项目后将jar包导入,然后在使用的页面上引入标签库:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- EL表达式配合使用JSTL
- 什么是EL表达式
全名为:Expression language,经常与JSTL配合使用,使得JSP页面更直观,写法更简单。
普通写法:<%=session.getValue("name") %>
EL表达式写法:<c:out value="${sessionScope.name }"></c:out>
-
- EL表达式的格式
用美元符号”$”定界,内容包括在花括号”{}”中;${表达式}
- JSTL核心标签的使用
- JSTL标签之out标签
- 输出常量
可在value属性中直接赋值
<c:out value=”this is our first JSTL demo”></c:out>
- 输出变量
变量不存在时可配合default属性输出默认值,还可通过escapeXml控制转移字符的输出方式。
<%session.setAttribute(“name”,”Jessica”);%>
<c:out value=”${name}”></c:out>
-
- JSTL标签之set标签
存值到scope中:可将值以变量形式存放在指定的范围中(2种形式)
<c:set value=”today” var=”day” scope=”session”></c:set>
<c:out value=”${day}”></c:out>
---------------------------------------未完,待续。。。。