day08 14
http协议 请求协议....响应协议......
响应行状态码:
以2开头,成功
以3开头,要转接
以4开头,客户端的错 404,访问了不存在的东西
以5开头,服务器的错 500,服务器代码异常
字符编码问题...
utf编码,表单数据提交使用的编码
day08 16
referer请求头(重要):统计访问量、防盗链
Tomcat把动态资源变成静态资源发送给浏览器,浏览器才能看懂
html页面中meta标签可以模拟响应头,注意不能模拟请求头
day08 18
设计验证码图片
day09
主要讲servlet的基本知识
day09 4
注意servlet会有线程安全问题(不是线程安全的)
day09 5
servlet是单例的,一个类就对应一个对象,当然不同类会有不同对象
day09 6
ServletConfig是个接口(今后遇到的很多都是接口!!!)
我们并没有写它的实现类,是因为tomcat帮我们提供了实现类(之前的AServlet是Servlet的实现类,是
我们自己写的,但是ServletConfig的实现类自己没有写,由Tomcat帮我们提供)
ServletConfig四个方法中,其实真正有用的是getServletContext(), 返回值ServletContext
day09 8
带参数的init方法才是真正的生命周期方法!!!!!
在GenericServlet的实现中,我们定义了一个空的init()方法,把它放在有参的init()方法中,
这样,在我们写一个Servlet类继承GenericServlet时,可以通过重写无参init()方式实现出生时要
GenericServlet实现了ServletConfig接口,ServletConfig能完成的内容它都能完成。
day09 9
错误码405:不支持这种请求方式。注意doGet和doPost方法本身不是抽象的,默认的实现是给
客户端一个405状态码。所有我们常常要重写这两个方法,这样就不会出现405了。
另外HttpServlet是抽象类,但是没有任何的抽象方法,说明你不能直接用我,你还得继承我。
创建Servlet类时,可以直接new-Servlet,这样web.xml自动帮我们配好了。不过自带的
Servlet模板比较烦,很多不需要的东西。
day09 12
Servlet与反射:在web.xml配置文件中通过url-pattern找到servlet-class字符串后,肯定要用反射
来创建Servlet对象(需要一个无参构造器)。
反射运用还是很广的,特别是谈到和配置文件相关的东西。重在理解,我们一般不需要写反射代码。
day09 13
一个项目只有一个ServletContext对象!!!常常给他取名application,把多个Servlet串起来
与天地同寿!服务器启动时创建,服务器关闭时死去!
day09 17
我觉得奇怪的是,getRealPath()不管输入什么字符串都行。。
day09 18
练习:统计网站访问量(在项目day09_3里面)
注意向浏览器输出使用到了response对象和PrintWriter流
day09 19
一个web项目,所有src下的东西都会在WEB-INF---classes出现
src下的东西将来不会发布给用户,只会发布WebRoot,所以src下的.java
会出现在WEB-INF中变成.class,而其他文件会原封不动地copy进来。
个人理解:要获取web根目录的资源(即WebRoot文件夹下的东西),用
17节讲的知识(即用ServletContext)比较
要获取类路径下的资源(ClassLoader用的多,统一不带斜线,而用Class还有
带和不带两种),用19节讲的知识。
即一个是ClassLoader的getResourceAsStream方法,
一个是ServletContext的getResourceAsStream方法
详见day09_2里面的DServlet和EServlet!!!!
另外EServlet还用到了方便操作流的类库,IOUtils。常用的工具类已下载。
day10
主要讲response,request
day10 1
MyEclipse的配置是基于工作空间的,换了工作空间以前的配置就没用了,
还得重新配置。
day10 2
request response对象是服务器创建的,浏览器一辈子和对象无缘
浏览器只能发送http请求,接收http响应。
request response生命短,请求结束就死了,有新的请求又创建新的request response。
day10 4
响应头,就是键值对!!注意可能存在一个名称对应多个值!!(比较少)
最重要的一个设置响应头方法setHeader():适用于单值的响应头
例如,response.setHeader("aaa","AAA");
response.setDataHeader("expires",1000*60*60*24);设置页面过期时间为一天
一般初学阶段设置为-1,即不让它缓存
day10 5 重定向
记住所有的重定向都要带上Location头!!!
响应头大小写都行,但一般首字母大写
重定向:response.setHeader("Location","/day10_1/CServlet");
其中,/day10_1/CServlet叫 请求URI (url与uri区别??)
/day10_1叫 项目名
/CServlet叫 Servlet路径(就是web.xml里面的url-pattern)
更清楚地理解重定向,可以使用chrome浏览器,开发者工具。
day10 6 定时刷新
能完成重定向、定时刷新等功能是因为浏览器能看懂这些头,
我们瞎写一个头那肯定不行。
乱码初体验...........
注意:重定向和定时刷新很相似,一个是立即,一个是过一段时间。
day10 7 禁用浏览器缓存
三管齐下:Cache-Control、pragma、expires
记不住这三个名字咋办,打开index.jsp,里面meta可以充当响应头。
day10 8 response响应体
getOutputStream和getWriter是互斥的,只能用其中一个!!!
同时用会抛IllegalStateException异常
字节流万能的,可以将字符串转化为字节数组(getBytes方法),再用getOutputStream
字符流不是万能的
响应体通常是html,也可以是图片
响应图片:day10_1/GServlet
day10 9
快速重定向:sendRedirect(String location) 方法
day10 10 request
获取常用信息:
获取客户端IP,request.getRemoteAddr()
获取请求方法,request.getMethod(),可能是POST或GET
注意:一般从地址栏输入或点超链接都是GET请求,提交表单我们设置为POST请求
时才是POST请求
获取HTTP请求头:
***最重要的方法,String getHeader(String name),适用于单值头
Enumeration其实是老版本的迭代器
User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393
5.1 XP
6.0 Vista
6.1 win7
day10 11 获取请求URL
一个完整的请求URL:
http://localhost:8080/day10_2/AServlet?username=xxx&password=yyy
有相应的方法获取里面的各部分内容,详见day10_2/CServlet
day10 12 防盗链
利用referer请求头!!详见day10_2 BServlet
day10 13 获取请求参数
无论是GET还是POST,获取请求参数方式都相同
比较重要的两个方法:
***String[] getParameter(String name);获取指定名称的请求参数值,适用于单值请求参数
***Map
getParameterMap();获取所有请求参数,可处理多值
想对ArrayList等输出,直接syso就行,因为重写了toString方法
想对数组输出,用Arrays.toString()方法
*****这个知识点比较重要!!!以后会经常遇到获取参数的例子,比如登录等等。
详见/day10_3/AServlet 其中发现一个问题,使用HTML5会产生乱码,HTML4不会,兼容问题?
day10 14 请求转发和请求包含(有点不好理解)
一个请求链中涉及到多个Servlet!!但总共就一个请求!!和重定向不同,重定向
实际上包含了两个请求。
这样理解:在客户端不知情的情况下,一个Servlet找另外的Servlet帮忙。因为总共
一个请求,所以Tomcat总共创建了一个request、一个response,大家的
Servlet都是相同的,因此可以在多个Servlet间共享数据,称之为request域。
javaweb,或者说Servlet中有三大域,这是第一个。
request和response经常是成对出现,需要一个作参数,往往也需要另一个。
***********response既能getHeader又能setHeader!!
请求转发(***):当前Servlet只能设置响应头(留头不留体),下一个Servlet又能设置头又能完成响应体。
别人找他帮忙,当然他比较牛逼。
请求包含:共同协作(都留)
***详见/day10_3/OneServlet和/day10_3/TwoServlet
注意一个重名的问题:
***在另一个包(比如servlet.include)中也可以有类名为OneServlet、TwoServlet的Servlet,但是,
Servlet名不能再是OneServlet、TwoServlet,最好加个前缀改成IncludeOneServlet、IncludeTwoServlet
因为web.xml配置文件中Servlet名不能重复!!!!
day10 16
Servlet中三大域对象:request、session、application,都有如下三个方法:
void setAttribute(String name, Object value)
Object getAttribute(String name)
void removeAttribute(String name) 一般对后面两个域对象用,因为他们命长,属性总留着占内存
同一请求范围内使用request.setAttribute()、request.getAttribute()来传值!!
对于重定向,第二个Servlet拿不到第一个Servlet设置的属性,因为是两个请求,第一个请求结束时
会杀死第一个request。而请求转发的话可以!!因为就是一个请求!!
注意,别把这里的属性和13节讲的参数搞混!!那里的参数是客户端发给服务器的。一提到request域,就是
一个范围包含了和属性(Attribute)相关的方法,和参数无关!!!
day10 17 乱码问题!!!!
响应编码...请求编码...
详见/day10_4/AServlet
day10 20 URL编码
它不是字符编码!!
表单会自动转,如果是一个链接中有中文参数需要我们自己转(用到后面JSP知识...)
day10 21 路径问题
感觉路径问题非常烦!!
ClassLoader获取资源时不能以“/”开头!
Class获取资源时不加“/”表示.class文件所在目录 加“/”表示classes文件夹下的目录,即与ClassLoader相同
day11 2 JSP基础
JSP其实就是一个Servlet,一个化了浓妆的Servlet。
JSP是服务员(作为请求发起页面和结束页面),Servlet是厨师(处理数据)
JSP包括html、java脚本(三种)、jsp标签(指令)
视频中提到的知识:
class MyClass{
成员
方法
构造器
构造代码块
静态块
内部类
}
关于java类中的非静态代码块和静态代码块 https://zhidao.baidu.com/question/393900964.html
day11 3
演示三种脚本怎么写。注意有些东西只学不用,实际中不会这么写
day11 4
讲Jsp和Servlet分工的案例(一个JSP中表单提交两个数,Servlet求和,在另一个Jsp页面中显示)
详见/day11_1/jia 文件夹
引发的问题:
Object obj = new Integer(100);
String strVal = (String)obj;
编译通过,运行出错
day11 5 JSP原理
注意看几个截图,JSP页面内容是怎么和翻译的.class内容对应的
JSP真身在Tomcat的work目录下!!
day11 6 注释
<%== ==%> 直接被忽略
这是html注释,浏览器能看见只是不显示
day11 7 Cookie入门
Cookie是不能跨浏览器的!!!
保存和获取Cookie:详见/day11_2/cookie1 文件夹
day11 8 cookie生命
详见/day11_2/cookie2 文件夹
day11 9 cookie的路径
cookie的路径不是设置这个cookie在客户端的保存路径!!!
浏览器访问服务器的路径,如果包含某个cookie的路径,那么就会归还这个cookie
day11 11 HttpSession入门
一个用户不可以同时拥有两个Session。打开两个浏览器算两个用户!!!
**********Cookie和Session:
Cookie保存在客户端,而Session是服务端对象,保存在服务端!!
Cookie和Http协议有关(有对应的请求头和响应头),而Session和Http协议无关。
day11 14 *****登录案例****
很重要的案例!!!详见/day11_3/session2文件夹
出现的问题:当用户名为中文时,保存cookie会出错,是需要URL编码么??
day11 15 HttpSession原理
貌似是我们一关浏览器,服务器就把session杀死。其实不是!!服务器根本不知道我们关了浏览器,
只是我们关闭浏览器时丢失了sessionID,新开浏览器又是新的sessionID(它对应一个cookie,生命设为-1)
因此,之前的session没人用了,过了一段时间(默认30分钟)服务器就把它抛弃了。
联想到日常经历:逛淘宝,登录以后,盯着一个页面看了很久,终于决定下单时又要重新登录...
使用JSP时,就已经创建session(内置对象),也有sessionId这个cookie。但是使用Servlet时就不一样了,
如果没有使用request.getSession()这个方法,就没有创建session,也没有sessionId。
day11 16
第一次自己写工具类:生成32位的随机十六进制字符串,以后还会经常写工具类。
位置:/day11_3/commons/CommonUtils
HttpSession其他方法:
有一个比较重要的方法:void invalidate() 让session失效,客户端再次请求创建新的session
比如:登录淘宝后,页面上有个“退出”按钮,用的就是这个方法
day11 17 url重写
浏览器禁用了cookie怎么办,把cookie用请求参数来替代!
day12 1
设计验证码图片**** /day11_3/image/VerifyCode
day12 2
在day11 14的登录案例中加入了验证码!!!
“看不清?换一张” 功能中,用到了JavaScript知识,每次请求VerifyCodeServlet换一张图,而不用
刷新页面。为了解决因浏览器缓存不换图的情况,每次设置src时加了一个总是变化的参数,骗浏览器用。
day12 4 page指令
JSP中三大指令:page、include、taglib,page最常用也最复杂
一个jsp页面中,可以有0~N个指令的定义!
任何异常出现,错误码都是500!!!
web.xml中配置错误页面
九大内置对象中,只有session和exception可能不能用:
**若当前页面session属性设置为false,则不能用session对象(基本没人这么干)
**当前页面isErrorPage属性设置为true时,才能用exception对象
其他内置对象肯定能有!!!
day12 5
pageContext一个顶九个!!!
注意page域指的就是pageContext的作用范围,和那个page内置对象(这个对象没啥用)没关系。
day12 6 另外两个指令 include和taglib
include是静态包含!!是在JSP编译成Java文件时完成的(大前期...)。因此不能包含一个变量名,因为
这个时候还不认识这个变量。
taglib:导入标签库
两个属性 prefix 、uri
day12 7 jsp动作标签
JSP2.0 20个动作标签,但大多没用。动作标签是由服务器解释执行,和HTML标签有本质区别。
标签前缀是固定的:jsp
包含有静态包含动态包含一说,转发没有。注意静态包含和动态包含的区别!!!
day12 8 关于一些配置的东西
在conf/context.xml中,可以在Context后这样配置,reloadable="true",这样不用总重启Tomcat。
但是这样做仅仅适用于项目开发阶段,而且有弊端。
day12 9 JavaBean
JavaBean的规范:
1、必须有默认构造器
2、提供get/set方法,如果只有get方法,那么这个属性是只读属性!
3、属性:有get/set方法的成员,还可以没有成员,只有get/set方法,属性名称由get/set方法来决定!
4、方法名称满足一定规范,那么它就是属性!boolean类型的属性,它的读方法可以是
is开头,也可以是get开头。
内省:
内省类--> Bean信息 --> 属性描述符 --> 属性的get/set对应的Method --> 可以反射了!
commons-beanutils 它是依赖内省完成,而内省又依赖反射!
* 导包
> commons-beanutils.jar
> commons-logging.jar
BeanUtils的使用*****
详见/day12_2/domain 包
以后可以一句话将表单数据封装到JavaBean中!!!
即用request.getParameterMap得到一个map,再将map转换到JavaBean中
因为以后表单数据可能很多,所以这样做很有效率!
day12 11 jsp中与JavaBean相关的标签
现在已经没人这么用了,这还是model1年代(不用Servlet,全是jsp)的做法。今天这种东西都在servlet中用。
day12 12 EL入门
JavaBean导航很重要,.加属性名等于调用get...方法
day12 13 11个内置对象
11个内置对象,10个是Map!!
*****以后项目名用 pageContext.request.contextPath 代替,这样客户改项目名也不怕了
EL表达式中session不是内置对象,不能直接用。但是有一个厉害的pageContext,它一个顶九个
即可以这么用:${pageContext.session.id} 获取JSESSIONID
详见/day12_3/WebRoot下的一系列文件夹
day12 14 EL函数库
都是一些字符串操作的函数
day13 2 JSTL概述
Apache的东西,依赖EL
四大库:core 核心库,重点
fmt 格式化:日期、数字
后面两个过时了
使用out标签可以防止JavaScript攻击,因为out标签里面默认escapeXML=“true”
out标签里面value后面跟的值必须加引号(里面可以写${...}),不能直接写变量
remove 删除域变量,注意默认是删除所有域
day13 4 url标签(重要)
* value:指定一个路径!它会在路径前面自动添加项目名
输出/day13_1/index.jsp
* 子标签:,给url后面添加参数,
输出为:/day13_1/index.jsp?username=%ED%2C%3F%ED%2C%3F
*var: 指定变量名,一旦添加了这个属性,url不输出到页面,而是保存到域中
以后需要写项目名有两种方法:
* ${pageContext.request.contextPath}/index.jsp 不用导库
* 需要导库
day13 5
if标签 相当于if语句
choose标签 相当于if..else if...
day13 6 forEach
可实现for foreach 的功能
***发现的问题:Java脚本里面设置的变量只有脚本里面能用,不能直接${...}输出
只有将变量设置到域中,才能在脚本外使用!!
***注意的问题:表现属性不要多写空格!!否则错误很难查出
day13 8 fmt标签
不足的话补位,四舍五入
不足的话不补位,四舍五入
day13 9 自定义标签
jsp2.0以后尽量不要用Java脚本。向域中设置参数可以用Servlet,再转发到jsp页面,然后jsp页面取数据就行,
可以用${}取数据。视频中写Java脚本是为了演示方便。
视频中导库写的是 uri="/WEB-INF/tlds/itcast-tag.tld"
我写的是 uri="http://www.nankai.cn/tags/1.0" 直接Alt+/找到的
貌似这两种方法都行。
实际中,不用实现SimpleTag接口来完成标签处理类,而是继承SimpleTagSupport类,它已经实现了该接口
就好比写Servlet我们也不是直接实现接口,而是继承HttpServlet类。
day13 13 MVC
不是Java独有的!
几乎是所有的web(B-S)都使用MVC!!!
M -- model 模型(直接写代码)
V -- view 视图(jsp)
C -- Controller 控制器(Servlet)
JavaWeb三层框架:
Web层 -- 与web相关内容(Servlet、JSP、request、response)
业务层 -- 业务对象(Service) request、response等不能出现在这!!
数据层 -- 操作数据库(DAO 即Data Access Object) 所有对数据库的操作不能跳出到DAO之外!!
day13 15
演示三层框架
day14 2
cn.itcast.web.servlet为什么还加个web,因为servlet是Javaweb三大组件之一,以后可能还加别的。
要学会看包名:
一般从第三段或第四段开始看(前面是公司名倒写),依次是项目名、模块名等。
day14 3
***导入jar包
***改Servlet模板
day14 4
不要污染Service!!!
day14 6~8 Dao层实现
注意:这里Dom4j的回写操作与我之前学的不一样,主要有两点:
1,设置OutputFormat,我直接用的“漂亮格式”,这里的更复杂一些
2,回写文件我用的FileOutputStream即字节流,这里说用字符流更好,并且设置了编码(更复杂)。
测试发现我的方法也行,没有乱码。
day14 13 加验证码
可以参照之前学的
注意一个问题:如果是IE浏览器,在js中通过id获取元素,如果另一个元素的name属性
也叫这个名字,则可能获取不到那个元素。(尽量别重名就行)
day14 12 表单校验
发现的问题:
EL表达式中可以直接写map.key的形式,比如视频中的${errors.username}
这应该不算JavaBean导航吧,算是EL表达式 的方便之处??
话说回来,EL的11个内置对象中10个是map,所以这也能说得通。
以后写Servlet,常常第一件事就是封装表单(或超链接参数)!!
day14 14 登录
以后玩登录,一登录成功,就将用户数据保存到session域中!!
注意为了不让硬闯,得先判断session中是否有用户,没有的话打回到登录页面。
day15 1 MySQL
我们常说的数据库指 RDBMS 关系型数据库管理系统
day15 2
可能数据库服务器和应用程序相隔很远!!
day15 4 删除MySQL
挺重要的!!要删干净不容易,包括一些注册表!!
day15 5
mysqld.exe 查查任务管理器中有没有,这是MySQL的服务器端程序,必须要有!
mysql.exe 这是客户端程序,用来连接服务器,可以开启多个
day15 7
SQL语言虽然是标准化语言,但每个数据库都有自己的一些方言。
比如MySQL里面的limit,Oracle看不懂。
day15 8
方括号里面表示可选的,自己写的话别加方括号。
day15 9
char与varchar:各有优缺点,varchar需要单独拿一个字节来记录长度。
关于varchar长度到底是字节还是字符:
貌似没有统一的答案。据说,4.0以下指字节,5.0以上指字符。
text是mysql独有的(官方是clob)
tinytext -- text -- mediumtext(16M多) -- longtext(4G) 超大文本
day15 12
字符串用单引号!!
发现的问题:
插入数据时,若是一个字符串,里面的空格都算。但是,如果该列数据类型是char,
而插入的字符串超出了,则会自动去掉末尾空格。仍然超出则报错。
day15 13
出现了 =null ,那就是false,要判断是不是null,应该用 is null。
day15 16
注意 + 并不能连接字符串,用concat('','')连接。oracle中俩竖线。
select concat('我叫',name,',我的工作是',job) from emp;
怎么处理Null select sal+ifnull(comm,0) from emp;
起别名 as可以省略
day15 18 模糊查询
使用关键字like _ 一个字符
% 0个或多个字符
day15 19
排序时,可以加多个指标,若第一个指标相同,则按第二个指标排序。
如:select * from emp order by sal asc, comm desc, empno asc;
day15 20
count(1),count(200)等等和count(*)效果一样,但没人这么用,就拍别人考。
day15 20 简单聚合函数
select count(*) 人数,sum(sal) 总和,max(sal) 最高,min(sal) 最低,avg(sal) 平均 from emp;
day15 21 分组查询
****************
在分组情况下,select 后只能跟组信息,包括两个,一是分组列,二是聚合函数。
如:select job,count(*) from emp group by job;
job是分组列(与后面的job对应),count是聚合函数,不能select name 。
一般养成习惯分组的话select后面先写分组列!!
select
from
where 分组前条件,没参与分组 (即分组前先把一部分干掉)
group by
having 分组后条件(经常是聚合函数)
order by
day16 2 编码问题(只针对小黑屏)
注意:Mysql其他内容是回家一段时间看的,这里没有笔记,截图也没有!!!后面直接进入JDBC。
day17 JDBC
背下来:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mydb1
com.mysql.jdbc.Driver这个驱动类是MySQL提供的,若变成了oracle,这个驱动类肯定要变。即各个数据库
厂商都提供了属于自己的驱动类,为了实现JDBC规范(其实是一组接口)。同理url也得跟着数据库而变。
Class.forname(...)加载驱动类。不写这个将找不到驱动。
注:新版本的驱动包不写这个也行,但最好还是写上吧。
四大参数!!!
JDBC协议格式!jdbc:厂商名称:子协议(由厂商自己规定)
对mysql而言,子协议结构://主机:端口号/数据库名称
JDBC一般对记录进行操作,很少对表结构进行操作!!
day17 3 实现增删改查
别忘了最后将资源关闭!! rs、stmt、con
day17 4 代码规范化
循环遍历rs时,若搞不清列的数据类型,用getString或getObject是通用的。
day17 5 滚动结果集
用得少 就next()用得多!
con.createStatement() 默认是不滚动,不敏感,不可更新!但是,MySQL默认是滚动的!
day17 7
SQL攻击,输入的用户名为SQL语句的片段,造成'a'='a'永远为真。
PreparedStatement的作用之一就是防止SQL攻击。
day17 10 JdbcUtils 1.0
这一节很难!!
用到了Properties类,配置文件,实际上是键值对。
用到了获取类路径下资源方法 JdbcUtils.class.getClassLoder().getResourceAsStream("...");
用到了static静态代码块。
day17 11 面向接口编程
思想很重要!!!
把UserDao修改为接口,并提供实现类,但是不是直接用实现类,而是通过工厂(DaoFactory)取实现类,
怎么取的?工厂通过配置文件(.properties)获取实现类的类名,再用反射得到实例,返回即可。
这样做的好处:最大程度解耦,全篇代码没有出现实现类的名字,若实现类变了,用户只需改配置文件,
而不用修改程序。
day17 12 day14DAO层的修改
代码见day14的代码。
JDBC连接数据库!!只需要写一个新的实现类即可,实现UserDao接口!!然后把配置文件改了,其他不用变!
里面用到了通过ClassLoader获取资源(获取的是个配置文件),并把相应代码放到static代码块中,最近常常用这个套路。
里面用到了ORM,对象关系映射,后期复杂的时候得用hibernate。
day17 13 时间类型转换
java.sql包下的东西绝对不能出现在DAO以外的地方!!
原则就是每一层只管自己这一层的东西,不要泄露给别的层。
另外,领域对象(domain)中的所有属性不能出现java.sql包下的东西!即不能使用java.sql.Date
这节考虑java.sql.Date和java.util.Date的转换问题
day17 14 大数据
把一首MP3放入数据库,然后读取出来放到磁盘上。
详见day17_1/...demo4
存MP3可用mediumblob类型。
需要在my.ini修改 max_allowed_packet,不然MySQL不让放这么大的数据。
IOUtils的使用!!!
IOUtils.toByteArray (输入流转换为字节数组)、IOUtils.copy (可以将输入流数据写入到输出流)
day17 15 批处理
详见day17_1/...demo5
pstmt.addBatch();
pstmt.executeBatch();
注意,很多人认为MySQL不能提供批处理,这是不对的!MySQL默认把批处理关闭了,需要在url后
配置参数 rewriteBatchedStatements=true。这样就能快很多!
另外,给程序计时:
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
syso(end-start);
day18 01
事务的四大特性(ACID),背下来!
day18 3
JDBC中处理事务,通过con完成。
记住,同一事务中所有的操作,都要使用同一个Connection对象!!!
这里写的是不完善的业务层(被JDBC的东西感染了),后面会解决(也不知道啥时候)。
day18 4 事务的隔离级别
并发读问题:
脏读(严重)
不可重复读
虚读
四大隔离级别:mysql用的是repeatable read(可重复读),Oracle用的是read committed(读已提交)
day18 5 数据库连接池
常量池、线程池、连接池。。
需要导入三个jar包,那个我们自己写的小工具类JdbcUtils就不用了,因为我们是用连接池创建连接,作用一样。
javax.sql 包下有一个DataSource接口,任何实现了它的类就是数据库连接池!!
我们用的连接池一般都是实现了这个接口的、第三方提供的连接池。
一般一个项目一个连接池就够了。
装饰者模式
*连接池内部使用四大参数创建了连接对象!即MySQL驱动提供的Connection
*连接池对Connection对象进行了装饰,只对close方法进行了增强
*装饰之后的Connection的close方法用来把当前连接归还给池!
*
day18 6 *****装饰者模式*****
在IO流中有大量使用!!
***对象增强手段:
*继承
*装饰者模式
*动态代理 (更加高级,AOP面向切面编程)
***是你还有你,一切拜托你!!!
装饰模式简单实例:给文件加密,见截图。
day18 7 c3p0连接池
据说它的作者是星球大战迷,c3p0是其中一个机器人名字。
它四大参数的配置 方法名字和dbcp有三个不一样...只有一个setPassword是一样的。
***C3P0底层用的动态代理,用System.out.println(con.getClass().getName());输出类名就清楚了
com.mchange.v2.c3p0.impl.NewProxyConnection proxy是代理的意思
day18 8 c3p0 配置文件
默认配置、命名配置
day18_3 demo1 配置文件中只写了默认配置
day18 9 JdbcUtils第二次更新
day18 10 JNDI配置
Catalina/locahhost 下创建 day18_4.xml,在这里给出... ,只对该项目有效
可参考 配置外部应用一节!!
JNDI配置好后,就是获取资源。获取资源的代码背下来就得了!
详见day18_4/AServlet 获取资源。
注:现在不太明白的是为什么要通过JNDI的方式来获取(感觉还麻烦一些),像之前那样直接获取貌似方便一些。
还有一点,若Tomcat下没有了那个项目(如day18_4),那么必须把day18_4.xml移除,不然出异常。
day18 11 ThreadLocal
其实不想共享数据,只想每个线程有自己的副本。
通常用在一个类的成员上,每个线程有自己的副本互不干扰,解决并发访问问题。
内部实现是个Map,使用当前线程(Thread.currentThread)作为key!!
这节涉及到的知识:多线程,通过匿名内部类方式创建多线程,不熟悉的话看以前知识和截图。
见视频day18_5 工程,这个我自己没写。
day18 12 dbUtils
将数据库的操作进一步简化。
详见day18_5 该节内容其实很多,建议再看视频!
day19 13 dbutils结果集处理器介绍
5个结果集处理器要记住!!2个转换为JavaBean,2个转换为Map,1个处理单行单列!
视频中分别进行了演示,我没写。
day19 1、2 BaseServlet
可以在Servlet中根据传过来的参数调用相应的方法(用反射)。
为了进一步简化转发和重定向,以字符串形式返回相应的操作。在Baseservlet中对字符串进行处理,
完成相应的操作。
详见day19_1 servlet包
day19 3 JdbcUtils的第三次修改
再次强调:开启事务,提交事务,回滚事务要用同一个连接!!!DAO层相应的连接也得是这个!!
两难问题:
DAO层不能出现事务!
Service层不能出现Connection!
解决:
把JdbcUtils修改为DAO层和Service层的中介!增加三个方法:开启事务、提交事务、回滚事务。
day19 4 TxQueryRunner
/**
* 这个类中的方法,自己处理连接问题,无需外界传递
* 怎么处理呢
* 通过JdbcUtils.getConnection得到连接
* 可能是事务连接也可能是普通连接
* 由JdbcUtils.release方法释放连接
* 释放连接包括两个方面,事务连接不关闭,普通连接关闭
* @author huli
*
day19 5 JdbcUtils处理多线程并发访问
就是把成员 Connection改为 ThreadLocal类型 ,每个线程有自己的Connection
day19 7
简单的客户关系管理系统
前端知识要补!!! frame、target、base的作用,jQuery
day19 8
总结小经验:一般都是jsp带着某些参数给servlet,处理完后把结果放到域中转发给jsp。
day19 9 *******
标签作用之一:
男
for属性的值要和上面标签的id值一致,这样可以将label的内容赋给input的value。
效果:并不一定非得点中那个小圈圈才能选中“男”,直接点“男”这个字就能选中!!
表单里面想加个参数咋办?
由于是post方式,不要用?后面加参数
可以直接在表单里面写个input加参数,为了防止用户看见,设置type=“hidden” ,视频叫隐藏字段。
day19 12 多条件组合查询
有技巧!!!
SQL利用StringBuilder追加,params利用ArrayList追加
SQL语句里面写 where 1=1 可以省很多事!
day20 分页处理
项目day20_0 是先复制了day19_3 ,然后加上分页处理。
注意复制项目后右键项目,选最后一项,改context Root
分页处理中一个难点,在高级搜索中如何保留查询条件!!
获取URL时注意把表单改成get方式,不然参数获取不到。(post方式参数不在URL里面)
对get请求注意编码处理问题,先退再编。
day20 8 监听器
事件源:三大域:
ServletContext、HttpSession、ServletRequest
生命周期监听、属性监听
用得比较多的:
对于ServletContext的“出生监听”,可以在这个监听器存放一些服务器一启动就要完成的代码!!
day20 11 session的序列化
session有死而复生的能力!!!
当服务器断开时,在Tomcat的work目录下存有SESSIONS.ser文件(保存到了硬盘上),保存有session。服务器又启动时会将这个
文件读回去。这样,项目上线后,若需重启服务器,用户也不用下线。
注意:在Tomcat的 context.xml文件中配置 可使这一功能作废。
day20 12 session的钝化和活化
在服务器没有断开的情况下,你一段时间(如一分钟)没有动作,则把session从内存中移到硬盘中(钝化)
若有活动了,则又加载到内存中(活化)。期间用户感觉不到。
如何进行配置见视频中。
一个类除了实现HttpSessionActivationListener接口外,还得实现serializable接口,才能陪session一起
钝化到硬盘,然后活化回来。
day21 2 过滤器
过滤器通常用来过滤一批资源,很少说只针对某个servlet过滤。
Filter接口的doFilter()方法,三个参数;
FilterChain的doFilter()方法,两个参数(用于放行)。注意区分。
多过滤器情况下,放行表示执行下一个过滤器,若没有了过滤器,则执行目标资源。这就是“链”。
如果被前一个拦截了没有放行,那就不会执行下一个了。
另外,多过滤器执行顺序是按配置中mapping的顺序。
day21 5
还可以在mapping中指定一个或多个servlet名字来过滤!!说明我就要针对你!!
day21 6 统计访问量
获取IP:request.getRemoteAddr();
可以把IP和对应的访问量放在一个map中,而在ServletContext监听器中完成map的创建,在过滤器完成map修改。
LinkedHashMap
day21 7 权限管理
由ServletRequest request得到session要强转!
给/WebRoot/users下的文件设置保安(filter):url应写 /users/* ,filter中得到session中用户,
设置成会员和管理员才能访问。
给/WebRoot/admin下的文件设置保安(filter):url应写 /admin/* ,filter中得到session中用户,
设置成只有管理员才能访问。
这个小案例我没写。
day21 8 ***全站编码问题***
装饰者模式的应用***
/*
* 重点!!!
* 如何解决get请求编码问题?
* 我们采用装饰者模式,写一个request的装饰类。
* 因为doFilter的参数会传递到目标资源中,所以我们可以
* 调包request,即在放行时,使用我们自己的request
*
* */
可以将/day21_4/cn.itcast.web.filter中的两个类保存,应用到其他项目中只需该web.xml文件,就不用
考虑编码问题了。(这里我将响应编码也放进去了,视频中只放了请求编码,响应编码还得在servlet中写)
另一个问题:
我们自己写一个装饰类EncodingRequest时,如果是实现HttpServletRequest接口,要实现太多的方法。
解决办法是有一个好人HttpServletRequestWrapper,它已经帮我们实现了,只需继承它,然后重写某个
需要装饰的方法即可。
day21 9-11 页面静态化
***核心思想:
这回我们对response进行装饰!!
对于一个JSP,默认在它真身里面都是用了response的getWriter向浏览器输出。
现在我们调包response,用我们自己写的response,对其getWriter方法进行装饰,使其向某路径下的
html文件输出。最后重定向到这个html。
注:为了解决html文件显示乱码问题,在jsp的 标签加一个模拟响应头;
实现以后效果:
第一次通过Servlet访问数据库,以后不访问servlet(因为被filter拦下了),直接重定向到一个html,
这样比较快。适合于页面长时间不变动的情况。
day22 5 文件上传代码演示
/*上传三步:
* 1 得到工厂
* 2 通过工厂创建解析器
* 3 解析request,得到FileItem集合
* 4 遍历FileItem集合,调用其API完成文件保存
* */
详见/day22_1
day22 7
Runtime run = Runtime.getRuntime();
这是个很危险的东西,run.exec()能执行一些dos命令,比如关机等。
所以上传文件一般放WEB-INF下。除非是项目要用到,那就放项目的目录下,否则(比如放到了C盘),那把项目发
给客户的时候这个文件就不会带走了。
shutdown -s -t 300 五分钟后关机
shutdown -a 取消
day22 10 文件同名问题解决
filename = CommonUtils.uuid() + "_" + filename;
day22 11 目录打散
我们用的是哈希打散,每个对象的哈希码(一般不同),int类型
有点难度,我没写,详见视频
day22 12 上传文件大小限制
特别注意!!!上传处理不能用BaseServlet!!因为BaseServlet是基于getParameter方法来获取到底调用了
哪个方法,而这个方法在上传文件的时候是作废的!!
day22 15 文件下载
获得某文件的MIME类型:
String contentType = this.getServletContext().getMimeType(filename);
/*
* 两个头一个流!
* 1 Content-Type
* 2 Content-Disposition
* 3 流:下载文件的数据
* */
最后 IOUtils.copy(in, response.getOutputStream());
注:谷歌浏览器不弹框,直接就下了。。。
day22 16 下载框中文件名乱码问题
考虑到不同浏览器版本,有一个比较万能的类DownUtils,详见截图。
day22 17 邮件协议
SMTP:简单邮件传输协议,发
POP3:邮局协议第三版, 收
邮件服务器名称(命名有规则的):
SMTP服务器端口号25,名称为smtp.xxx.xxx
POP3服务器端口号110,名称为pop3.xxx.xxx
如:smtp.163.com 和 pop3.163.com
day22 18 telnet发邮件
Xshell
Base64编码,和url编码一样不是字符编码!!编程奇奇怪怪肉眼无法识别的字符串!
怎么解决BASE64Encoder类不能用的问题?详见视频。
day22 19 javamail发送邮件
注意一个视频中没提到的问题,需要在邮箱中设置第三方授权密码,否则连不上smtp.163.com.
详见/day22_3
day22 20 带有附件的邮件
解决附件文件名称中文乱码问题,使用MimeUtility.encodeText();处理
day22 21 MailUtils
使用小工具简化邮件发送!!!真的简便多了...
day23 ajax
注意,POST请求的话需要自己设置一个请求头:Content-Type
get请求见 ajax1.jsp post请求见ajax2.jsp
第三例:判断用户名是否已被注册,onblur事件发生时异步发送请求给服务器
这个例子我没写。
第四例:响应内容为xml
第五例:***省市联动***,比较复杂的一个例子,没写。
XStream
作用:可以把JavaBean转换为(序列化)为xml
把数据库查找的结果集转为对象我们已经学过,这里是进一步把对象转为xml,便于与ajax对接!
json-lib
JavaBean转为json!!!
依赖很多jar包,还没下载
其实重点掌握是JQuery封装好的ajax!!!见新加入的视频
$.get(4个参数) $.post(4个参数)
这两个都默认是异步请求,eval方法封装好了,不用自己写,Content-Type请求头也不用自己设置
$.ajax(json对象)
——————————————————————————————图书商城项目——————————————————————————————
小总结:
该项目采用JavaWeb三层架构,数据库使用MySQL,维护用户、图书、订单等五张表。项目实现用户登录校验、
邮箱激活、分类浏览、添加购物车、订单生成、第三方支付等功能,有必要时提供过滤器拦截页面。
管理员后台登录可对商品、订单进行管理。
普通超链接在 里面写文字就行
用图片做超链接在里面放
要想实现鼠标悬停时改变样式(比如更换一张颜色更深的图片), 里面什么都不写,
在页面中设置CSS样式:比如(直接从项目中复制的):
a {
background: url( ) no-repeat;
display: inline-block;
background-position: 0 -70px;
margin-left: 30px;
height: 36px;
width: 146px;
}
a:HOVER {
background: url( ) no-repeat;
display: inline-block;
background-position: 0 -106px;
margin-left: 30px;
height: 36px;
width: 146px;
}
当用超链接提交表单时:
这样就能使提交按钮做出想要的效果
2.0-1.1 得到不是0.9,而是0.89999999999
Java中提供了BigInteger和BigDecimal处理精度丢失问题
double d1 = 2.0;
double d2 = 1.1;
BigDecimal d3 = new BigDecimal(2.0+"");
BigDecimal d4 = new BigDecimal(1.1+"");
System.out.println(d1-d2);
System.out.println(d3.subtract(d4).doubleValue());
这样就没问题了
值得注意的是,必须采用字符串的构造方法,否则还是一样丢失精度!!
用BeanHandler完成ORM映射时,若缺少字段,即select的时候只选了部分,一样能映射出一个对象,
只是部分值为null。
CommonUtils.toBean封装对象时,若给的Map含有多余的键值对,一样能封装成功,多余的忽略就行。
day27
*************注解*****************
给包上加注解可以,但是不能用普通方式。这东西没用不用管了。
注意:注解在Eclipse上显示的是灰色!以后看到灰色就要联想到注解!
当属性是一维数组只有一个元素时可以去掉大括号,这时候就容易混淆。比如:
f=100不知道f是int类型还是int[]类型去掉了大括号。得格外小心!
day28
动态代理
代理对象的所有方法都会调用InvocationHandler的invoke()方法,但有些方法除外:
这些方法是本地方法,即Object.class文件中标有native关键字的方法,如 getClass()
day28 7
****动态代理很有用的案例。
day28 9
类加载器的委托机制保证了程序的安全!比如如果你想写一个String类企图覆盖系统的String类,
门都没有,因为类加载器会先去找系统类库中的东西,找不到再找扩展的,再找不到才是你写的。
类加载器还得分线程,每一个线程有自己的类加载器负责加载。
小技巧:
要看一个方法调用栈,可以故意让它抛出异常(如果可以的话),这样异常信息就是调用栈了,
比debug快很多。
既然所有类都是类加载器加载的,那类加载器哪来的?都是由引导类加载器加载的。那引导类加载器又是
哪来的呢?答案是,它是JVM的一部分,相当于是自带的!