总结了Day01 到 Day09 的知识
文章目录
一、servlet
Servlet的体系结构:HttpServlet extends GenericServlet extends Servlet
Servlet -- 接口
|
GenericServlet -- 抽象类
|
HttpServlet -- 抽象类
二、HTTP
1.HTTP请求消息数据格式

* 请求消息数据格式
1. 请求行
请求方式 请求url 请求协议/版本
GET /login.html HTTP/1.1
* 请求方式:
* HTTP协议有7中请求方式,常用的有2种
* GET:
1. 请求参数在请求行中,在url后。
2. 请求的url长度有限制的
3. 不太安全
* POST:
1. 请求参数在请求体中
2. 请求的url长度没有限制的
3. 相对安全
2. 请求头:客户端浏览器告诉服务器一些信息
格式:“请求头名称: 请求头值”
* 常见的请求头:
1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
2. Referer:http://localhost/login.html
* 告诉服务器,我(当前请求)从哪里来?
* 作用:
1. 防盗链:
2. 统计工作:
3. 请求空行
空行,就是用于分割POST请求的请求头,和请求体的。(Get请求没有请求空行和请求体)
4. 请求体(正文):
* 封装POST请求消息的请求参数的。(Get请求没有请求空行和请求体)
2.HTTP响应消息数据格式

2. 响应消息:服务器端发送给客户端的数据
* 数据格式:
1. 响应行
1. 组成:协议/版本 响应状态码 状态码描述
什么是响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
状态码都是3位数字 :
1. 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
2. 2xx:成功。代表:200
3. 3xx:重定向。代表:302(重定向),304(访问缓存)
302:浏览器访问A资源,A资源发了个302(重定向)说我办不了你找C去吧。
304:浏览器访问了一张图片并把它缓存下来,当它再次访问这张图片时该图片就会发出304表示你本地有缓冲,你从缓冲里面找吧
5. 4xx:客户端错误。
* 代表:
* 404(请求路径没有对应的资源)
* 405:请求方式没有对应的doXxx方法(你代码里面删掉了doGet方法,你启动servlet,浏览器访问该页面就会报错为405)
6. 5xx:服务器端错误。代表:500(服务器内部出现异常)
2. 响应头:
1. 格式:头名称: 值
2. 常见的响应头:
1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* 值:
* in-line:默认值,在当前页面内打开
* attachment;filename=xxx:以附件形式打开响应体。文件下载
3. 响应空行
4. 响应体:传输的数据
三、request的功能
1.获取路径相关
request.getContextPath() /day14
request.getRequestURI() /day14/demo1
request.getRequestURL() http://localhost/day14/demo1
2. 获取请求头数据
request.getHeader("user-agent")
request.getHeaderNames():获取所有的请求头名称
3.获取请求参数
request.getParameter("username");
request.getParameterValues("hobby");
request.getParameterNames();
request.getParameterMap();
4.设置编码:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码,需要request.setCharacterEncoding("utf-8");
* 设置了编码以后request.getParameter("username");//获取到的username是“张三”也不会乱码了
5.请求转发
你可以看到request的主要功能都是获取get方法(获取请求头、获取参数、获取请求体等等)
一旦要是出现了set方法那就是要走人了(先setAttribute,然后就是拿着属性转发走了)
request.setAttribute("msg","hello");
request.getAttitude("msg");
request.removeAttribute("msg");
request.getRequestDispatcher("/requestDemo9").forward(request,response);
1. 获取请求消息数据
原文中有很多,以下是我提炼出的需要你重点掌握的几个:
1. 获取请求消息数据
1. 获取请求行数据
* 请求行的格式:GET /day14/demo1?name=zhangsan HTTP/1.1
* 方法:
1. (*重点*)获取虚拟目录:/day14
* String getContextPath()
2. (*重点*)获取请求URI:/day14/demo1
* String getRequestURI(): /day14/demo1
* StringBuffer getRequestURL() :http://localhost/day14/demo1
* URL:统一资源定位符 : http://localhost/day14/demo1
* URI:统一资源标识符 : /day14/demo1
* URI相当于“共和国”,URL相当于“中华人民共和国”,URI的范围要大于URL的范围
2. 获取请求头数据
* 方法:
* (*重点*)String getHeader(String name):通过请求头的名称获取请求头的值
* Enumeration<String> getHeaderNames():获取所有的请求头名称
1. 获取请求行数据实例
//访问网址"localhost:8080/day14/requestDemo1?name=zhangsan"
@WebServlet("/requestDemo1")
//2.(*)获取虚拟目录:/day14
String contextPath = request.getContextPath();
//5.(*)获取请求URI:/day14/demo1
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
2. 1获取请求头数据实例1
@WebServlet("/requestDemo3")
//演示获取请求头数据:user-agent
String agent = request.getHeader("user-agent");
//判断agent的浏览器版本
if(agent.contains("Chrome")){
//谷歌
System.out.println("谷歌来了...");
}else if(agent.contains("Firefox")){
//火狐
System.out.println("火狐来了...");
}
//访问网址"localhost:8080/day14/requestDemo3
//输出“谷歌来了”
2. 2获取请求头数据实例2
@WebServlet("/requestDemo4")
//演示获取请求头数据:referer
String referer = request.getHeader("referer");
System.out.println(referer);//http://localhost/day14/login.html
//防盗链
if(referer != null ){
if(referer.contains("/day14")){
//正常访问
System.out.println("播放电影....");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("播放电影....");
}else{
//盗链
System.out.println("想看电影吗?来优酷吧...");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("想看电影吗?来优酷吧...");
}
}
//访问网址"localhost:8080/day14/requestDemo4
2. 3获取请求头数据实例3
@WebServlet("/requestDemo2")
//获取所有请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
//根据名称获取请求头的值
String value = request.getHeader(name);
System.out.println(name+"---"+value);
}
2. 获取请求参数(重点*)
1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1. String getParameter(String name):根据参数名称获取参数值
比如请求参数是username=zs&password=123,你调用getParameter(username)得到的就是zs
2. String[] getParameterValues(String name):根据参数名称获取参数值的数组,经常用于复选框这种的
像复选框你得到的请求参数是hobby=studey&hobby=game,你调用getParameterValues(hobby)得到的就是[study,game]
4. Enumeration<String> getParameterNames():获取所有请求的参数名称
5. Map<String,String[]> getParameterMap():获取所有参数的map集合
* 中文乱码问题:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码
* 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");


3. 获取请求参数中文乱码问题(重点*)
* 中文乱码问题:
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码
* 解决:在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
@WebServlet("/requestDemo7")
//doGet里面:
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");//获取到的username是“张三”也不会乱码了
//doPost:
this.doPost(request,response);
4.请求转发(重点)
请求转发:一种在服务器内部的资源跳转方式
1. 步骤:
1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
2. 特点(面试常问!!):
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求
共享数据:
* 域对象:一个有作用范围的对象,可以在范围内共享数据
* request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
* 方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttitude(String name):通过键获取值
3. void removeAttribute(String name):通过键移除键值对
你可以看到request的主要功能都是获取get方法(获取请求头、获取参数、获取请求体等等)
一旦要是出现了set方法那就是要走人了(先setAttribute,然后就是拿着属性转发走了)
@WebServlet("/requestDemo8")
doPost:
System.out.println("demo8888被访问了。。。");
request.setAttribute("msg","hello");
request.getRequestDispatcher("/requestDemo9").forward(request,response);
doGet:
this.doPost(request,response);
@WebServlet("/requestDemo9")
doPost:
Object msg = request.getAttribute("msg");
System.out.println(msg);
System.out.println("demo9999被访问了。。。");
doGet:
this.doPost(request,response);

2. 特点(面试常问!!):
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求
四、用户登录案例
Day04_用户登录案例(含BeanUtils的使用)
这个案例很重要,至少BeanUtils你得知道吧?
五、Response对象的功能
//设置状态码、请求头
response.setStatus(302);
response.setHeader("location","/day15/responseDemo2");
//设置编码,输出数据
response.setContentType("text/html;charset=utf-8");
ServletOutputStream sos = response.getOutputStream();
sos.write("你好".getBytes("utf-8"));
//完成重定向
response.sendRedirect("/day15/responseDemo2");
1.关于response
* 功能:设置响应消息
1. 设置响应行
1. 格式:HTTP/1.1 200 ok
2. 方法:
设置状态码:setStatus(int sc)
2. 设置响应头:
setHeader(String name, String value)
3. 设置响应体:
* 使用步骤:
1. 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2. 使用输出流,将数据输出到客户端浏览器
2.完成重定向
1. 完成重定向
* 重定向:资源跳转的方式
* 代码实现:
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location,告诉B资源的资源路径
response.setHeader("location","/day15/responseDemo2");
* 简单的重定向方法替代上面的代码:
response.sendRedirect("/day15/responseDemo2");
@WebServlet("/responseDemo1")
doPost:
System.out.println("demo1........");
/*复杂的方法:
response.setStatus(302);
response.setHeader("location","/day15/responseDemo2");*/
//动态获取虚拟目录
String contextPath = request.getContextPath();
//简单的重定向方法
response.sendRedirect(contextPath+"/responseDemo2");
doGet:
this.doPost(request,response);
@WebServlet("/responseDemo2")
doPost:
System.out.println("demo2222222........");
doGet:
this.doPost(request,response);
3.重定向的特点:
* 重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
* 转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
4.路径的写法
* 路径写法:
1. 路径分类
1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路径
* 规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost/day15/responseDemo2
(事实上/day15/responseDemo2就是绝对路径,因为http是协议,localhost是主机,都都可以省略)
* 以/开头的路径(如/day15/responseDemo2)
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
举例:<a>标签里的超链接路径,<form>表单路径,重定向都是给客户端用的,都需要虚拟路径
* 建议虚拟目录动态获取:request.getContextPath()
* 给服务器使用:不需要加虚拟目录
* 举例:转发路径(转发路径就是给服务器用的,就不需要用虚拟目录)
*你站在3班门口喊张三,那么只会三班的张三出来;你站在走廊里喊张三,那么三班和四班的张三都可能出来
所以站在走廊里喊张三需要加上“三班的张三”才能喊出那个人
给客户端浏览器使用就需要加上虚拟目录也是这个道理




5.服务器输出数据到浏览器
1.服务器输出字符数据到浏览器:
1.服务器输出字符数据到浏览器:
* 步骤:
1. 获取字符输出流
2. 输出数据
* 注意:
* 乱码问题:
//简单的形式,设置编码,是在获取流之前设置
response.setContentType("text/html;charset=utf-8");
@WebServlet("/responseDemo4")
doPost:
//简单的形式,设置编码
response.setContentType("text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter pw = response.getWriter();
//2.输出数据
pw.write("你好啊啊啊 response");
doGet:
this.doPost(request,response);
2. 服务器输出字节数据到浏览器
2. 服务器输出字节数据到浏览器
* 步骤:
1. 获取字节输出流
2. 输出数据
@WebServlet("/responseDemo5")
doPost:
response.setContentType("text/html;charset=utf-8");
//1.获取字节输出流
ServletOutputStream sos = response.getOutputStream();
//2.输出数据
sos.write("你好".getBytes("utf-8"));
doGet:
this.doPost(request,response);
六、ServletContext对象:
ServletContext context = request.getServletContext();
ServletContext context = this.getServletContext();
context.setAttribute("msg","haha");
context.getAttribute("msg");
context.removeAttribute("msg");
context.getMimeType("a.jpg");
context.getRealPath("/WEB-INF/c.txt");
1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信
2. 获取:
1. 通过request对象获取
request.getServletContext();
2. 通过HttpServlet获取
this.getServletContext();
3. 功能:
1. 获取MIME类型:
* MIME类型:在互联网通信过程中定义的一种文件数据类型
* 格式: 大类型/小类型 如:text/html 如:image/jpeg
* 获取:String getMimeType(String file)
2. ServletContext对象是域对象----可以共享数据
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
* ServletContext对象范围:所有用户所有请求的数据
3. 获取文件的真实(服务器)路径
1. 方法:String getRealPath(String path)
String b = context.getRealPath("/b.txt");//web目录下资源访问
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
1.获取ServletContext
@WebServlet("/servletContextDemo1")
doPost:
//1. 通过request对象获取
ServletContext context1 = request.getServletContext();
//2. 通过HttpServlet获取
ServletContext context2 = this.getServletContext();
doGet:
this.doPost(request,response);
2. 获取MIME类型:
@WebServlet("/servletContextDemo2")
ServletContext context = this.getServletContext();
String filename = "a.jpg";//image/jpeg
String mimeType = context.getMimeType(filename);
System.out.println(mimeType);
3.ServletContext对象是域对象----可以共享数据
@WebServlet("/servletContextDemo3")
doPost:
ServletContext context = this.getServletContext();
context.setAttribute("msg","haha");
@WebServlet("/servletContextDemo4")
ServletContext context = this.getServletContext();
Object msg = context.getAttribute("msg");
System.out.println(msg);//haha
4.获取文件的真实(服务器)路径

七、文件下载案例
* 文件下载需求:
1. 页面显示超链接
2. 点击超链接后弹出下载提示框
任何资源都必须弹出下载提示框,使用响应头设置资源的打开方式:content-disposition:attachment;filename=xxx
3. 完成图片文件下载
* 注意:
设置了这个响应头之后,不管什么资源都不会在浏览器中打开了,而是以附件的形式弹出:
content-disposition:attachment;filename=xxx
* 步骤:
1. 写html页面,编辑超链接href属性,指向Servlet,传递资源名称filename
2. 定义Servlet
1. 获取文件名称
2. 使用字节输入流加载文件进内存
3. 指定response的响应头: content-disposition:attachment;filename=xxx
4. 将数据写出到response输出流
1. 写html页面

<a href="/day15/downloadServlet?filename=九尾.jpg">图片1</a>
//编辑超链接href属性,指向Servlet,传递资源名称filename
<a href="/day15/downloadServlet?filename=1.avi">视频</a>
2.解决中文文件名问题

3.编写DownloadServlet
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数(获取要下载的文件名称)
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
//解决中文文件名问题
//1.获取user-agent请求头、
String agent = request.getHeader("user-agent");
//2.使用工具类方法编码文件名即可
filename = DownLoadUtils.getFileName(agent, filename);//把"user-agent"和filename传进去就可以返回一个新的filename
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1){
sos.write(buff,0,len);
}
fis.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
八、Cookie
response.setContentType("text/html;charset=utf-8");
Cookie c = new Cookie("msg","hello");
c.setPath("/");
c.setMaxAge(30);
c.setDomain(".baidu.com");
response.addCookie(c);
Cookie[] cs = request.getCookies();
if(cs != null){
for (Cookie c : cs) {
String name = c.getName();
String value = c.getValue();
System.out.println(name+":"+value);
}
}
1. 概念:客户端会话技术,将数据保存到客户端
2. 快速入门:
* 使用步骤:
1. 创建Cookie对象,绑定数据
* new Cookie(String name, String value)
2. 发送Cookie对象
* response.addCookie(Cookie cookie)
3. 获取Cookie,拿到数据
* Cookie[] request.getCookies()
3. 实现原理
* 基于响应头set-cookie和请求头cookie实现
4. cookie的细节
1. 一次可不可以发送多个cookie?
* 可以
* 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
2. cookie在浏览器中保存多长时间?
1. 默认情况下,当浏览器关闭后,Cookie数据被销毁
2. 持久化存储:
* setMaxAge(int seconds)
1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
2. 负数:默认值
3. 零:删除cookie信息
3. cookie能不能存中文?
* 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
str = URLEncoder.encode(str,"utf-8");
Cookie cookie = new Cookie("lastTime",str);
response.addCookie(cookie);
4. cookie共享问题?
1. 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
* 默认情况下cookie不能共享(/day15获取不到/day16的数据)
cookie1.setPath("/day16");就意味着只有虚拟目录为/day16下的才能访问
cookie1.setPath("/");管它什么/day15还是/day16都可以访问,因为它们都在同一个tomcat上
* setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
* 如果要共享,则可以将path设置为"/"
2. 不同的tomcat服务器间cookie共享问题?
* setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
比如setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享
5. Cookie的特点和作用
1. cookie存储数据在客户端浏览器
2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)
* 作用:
1. cookie一般用于存出少量的不太敏感的数据(你想,存储数据在客户端浏览器所以不安全)
2. 在不登录的情况下,完成服务器对客户端的身份识别
快速入门
@WebServlet("/cookieDemo1")
//1.创建Cookie对象
Cookie c = new Cookie("msg","hello");
//2.发送Cookie
response.addCookie(c);
@WebServlet("/cookieDemo2")
//3. 获取Cookie
Cookie[] cs = request.getCookies();
//获取数据,遍历Cookies
if(cs != null){
for (Cookie c : cs) {
String name = c.getName();
String value = c.getValue();
System.out.println(name+":"+value);
}
}
一次发送多个cookie
@WebServlet("/cookieDemo3")
//1.创建Cookie对象
Cookie c1 = new Cookie("msg","hello");
Cookie c2 = new Cookie("name","zhangsan");
//2.发送Cookie
response.addCookie(c1);
response.addCookie(c2);
cookie持久化存储
@WebServlet("/cookieDemo4")
//1.创建Cookie对象
Cookie c1 = new Cookie("msg","setMaxAge");
//2.设置cookie的存活时间
//c1.setMaxAge(30);//将cookie持久化到硬盘,30秒后会自动删除cookie文件(意味着30s后你就访问不到了)
//c1.setMaxAge(-1);
//c1.setMaxAge(0);//手动删除Cookie,意味着这个代码一执行你就访问不到了
//3.发送Cookie
response.addCookie(c1);
setPath("/")
@WebServlet("/cookieDemo5")
//1.创建Cookie对象
Cookie c1 = new Cookie("msg","你好");
//设置path,让当前服务器下部署的所有项目共享Cookie信息
c1.setPath("/");
//3.发送Cookie
response.addCookie(c1);
cookie小案例
1. 需求:
1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应的消息体的数据格式以及编码
response.setContentType("text/html;charset=utf-8");
//1.获取所有Cookie
Cookie[] cookies = request.getCookies();
boolean flag = false;//表示没有为lastTime的cookie
//2.遍历cookie数组
if(cookies != null && cookies.length > 0){
for (Cookie cookie : cookies) {
//3.获取cookie的名称
String name = cookie.getName();
//4.判断名称是否是:lastTime
if("lastTime".equals(name)){
//有该Cookie,不是第一次访问
flag = true;//有lastTime的cookie
//设置Cookie的value
//获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
//存数据之前应该使用URL编码将数据转换,这样cookie才能支持
str_date = URLEncoder.encode(str_date,"utf-8");
cookie.setValue(str_date);//因为你有cookie而且cookie的键为lastTime值咱不知道,所以你必须重新赋值
//设置cookie的存活时间(即使你关掉浏览器重新访问依旧保留着cookie信息)
cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
response.addCookie(cookie);
//响应数据
//获取Cookie的value,时间
String value = cookie.getValue();
//得进行URL解码,要不然你也看不懂啊
value = URLDecoder.decode(value,"utf-8");
response.getWriter().write("<h1>欢迎回来,您上次访问时间为:"+value+"</h1>");
break;
}
}
}
if(cookies == null || cookies.length == 0 || flag == false){
//没有,第一次访问
//设置Cookie的value
//获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
//存数据之前应该使用URL编码将数据转换,这样cookie才能支持
str_date = URLEncoder.encode(str_date,"utf-8");
Cookie cookie = new Cookie("lastTime",str_date);
//设置cookie的存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//一个月
response.addCookie(cookie);
response.getWriter().write("<h1>您好,欢迎您首次访问</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
九、jsp
1. 概念:
* Java Server Pages: java服务器端页面
* 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
* 用于简化书写!!!
2. 原理
* JSP本质上就是一个Servlet
3. JSP的脚本:JSP定义Java代码的方式
1. <% 代码 %>:定义的java代码,会被解析到service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
2. <%! 代码 %>:定义的java代码,会被解析到servlet的成员变量的位置。我们很少使用这个,因为之前学过servlet尽量不要定义成员变量。
3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
4. JSP的内置对象:
* 在jsp页面中不需要获取和创建,可以直接使用的对象
* jsp一共有9个内置对象。今天学习3个:
* request
* response
* out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似
* response.getWriter()和out.write()的区别:
response.getWriter()数据输出永远在out.write()之前,不过我们一般不使用response.getWriter()
out.write()是由上到下按顺序执行的,经常使用

十、session
HttpSession session = request.getSession();
session.setAttribute("msg","hello session");
session.getAttribute("msg");
session.removeAttribute("msg");
1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
2. 快速入门:
1. 获取HttpSession对象:
HttpSession session = request.getSession();
2. 使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
3. 原理
* Session的实现是依赖于Cookie的。
4. 细节:
1. 当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
* 默认情况下。不是。(当你关闭浏览器后一次对话就结束了)
* 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
* 不是同一个。
服务器重启导致session对象变化了,那么数据就会丢失,要确保数据不丢失。tomcat自动完成以下工作
* session的钝化:
* 在服务器正常关闭之前,将session对象系列化到硬盘上
* session的活化:
* 在服务器启动后,将session文件转化为内存中的session对象即可。
*这一切都不需要你操心,tomcat会自动完成上面的操作,数据就不会丢失
3. session什么时候被销毁?
1. 服务器关闭
2. session对象调用invalidate() 。
3. session默认失效时间 30分钟(也就是打开一个网站30分钟没有做任何操作,session会失效,你需要重新登录)
选择性配置修改session默认失效时间
<session-config>
<session-timeout>30</session-timeout>
</session-config>
5. session的特点
1. session用于存储一次会话的多次请求的数据,存在服务器端
2. session可以存储任意类型,任意大小的数据
* session与Cookie的区别:
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据大小限制,Cookie有
3. session数据安全,Cookie相对于不安全
快速入门
@WebServlet("/sessionDemo1")
//使用session共享数据
//1.获取session
HttpSession session = request.getSession();
//2.存储数据
session.setAttribute("msg","hello session");
@WebServlet("/sessionDemo2")
//1.获取session
HttpSession session = request.getSession();
//2.获取数据
Object msg = session.getAttribute("msg");
System.out.println(msg);
期望客户端关闭、服务器不关闭,session也能相同
@WebServlet("/sessionDemo3")
//1.获取session
HttpSession session = request.getSession();
//期望客户端关闭后,session也能相同
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);//一个小时
response.addCookie(c);
十一、验证码案例—session的使用
1. 案例需求:
1. 访问带有验证码的登录页面login.jsp
2. 用户输入用户名,密码以及验证码。
* 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
* 如果验证码输入有误,跳转登录页面,提示:验证码错误
* 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您



login.jsp(仅供了解)

success.jsp(仅供了解)

CheckCode.servlet(仅供了解)

Login.Servlet(核心,重点!!!)
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置request编码
request.setCharacterEncoding("utf-8");
//2.获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
//3.先获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String) session.getAttribute("checkCode_session");
//3.先判断验证码是否正确
if(checkCode_session.equalsIgnoreCase(checkCode)){
//忽略大小写比较用户输入的验证码和生成的验证码
//验证码正确后判断用户名和密码是否一致
if("zhangsan".equals(username) && "123".equals(password)){//本来该用数据库实现
//登录成功,存储信息,用户信息
session.setAttribute("user",username);
//重定向到success.jsp(重定向需要加虚拟目录)
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else{
//登录失败,存储提示信息到request
request.setAttribute("login_error","用户名或密码错误");
//转发到登录页面(转发不需要虚拟目录)
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else{
//验证码不一致
//存储提示信息到request
request.setAttribute("cc_error","验证码错误");
//转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
十二、JSP续学
1.指令
1. 指令
* 作用:用于配置JSP页面,导入资源文件
* 格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
* 分类:
1. page : 配置JSP页面的
* contentType等同于之前学的response.setContentType(),它有两个含义:
1. 设置响应体的mime类型以及字符集
2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="GBK" %>
* import:导包
* errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
<%@ errorPage="error.jsp" %>
* isErrorPage:标识当前也是是否是错误页面。
* true:是,可以使用内置对象exception
* false:否。默认值。不可以使用内置对象exception
也就是说只有<%@ isErrorPage="true" %>你才能使用String message = exception.getMessage();out.print(message);这段代码
2. include :将来很多页面的一部分内容是一样的,我们可以编写一个页面然后让其它页面包含这个页面就可以了,这就不用你重复编写了。
* <%@include file="top.jsp"%>
3. taglib : 导入资源
* <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
* prefix:前缀,自定义的,像定义成什么就定义成什么
2.注释
1. html注释:
<!-- -->:只能注释html代码片段
2. jsp注释:推荐使用
<%-- --%>:可以注释所有
3.内置对象(面试重点)
3. 内置对象
* 在jsp页面中不需要创建,直接使用的对象
* 一共有9个:
变量名 真实类型 作用
* pageContext PageContext 共享当前页面的资源,还可以获取其他八个内置对象
* request HttpServletRequest 共享一次请求访问的多个资源(如:转发)
* session HttpSession 共享一次会话的多个请求间的资源(如:重定向等)
* application ServletContext 共享所有用户间共享资源
* response HttpServletResponse 响应对象
* page Object 当前页面(当前Servlet)的对象,可以理解为this
* out JspWriter 输出对象,数据输出到页面上
* config ServletConfig Servlet的配置对象
* exception Throwable 异常对象
pageContext共享当前页面的资源

pageContext还可以获取其他八个内置对象

exception对象

十三、EL表达式
1. 概念:Expression Language 表达式语言
2. 作用:替换和简化jsp页面中java代码的编写
3. 语法:${表达式}
4. 注意:
* jsp默认支持el表达式的。如果要忽略el表达式
1. 设置jsp中page指令中:isELIgnored="true" 忽略当前jsp页面中所有的el表达式
2. \${表达式} :忽略当前这个el表达式
5. 使用:
1. 运算:
* 运算符:
1. "加减乘除"中除可以用/或div表示,取余可以用%或mod表示
2. 逻辑运算符: &&(and) ||(or) !(not)
3. 空运算符: empty (重点)
* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
* ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0
* ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0
2. 获取值(重点)
1. el表达式只能从域对象中获取值
2. 语法:
1. ${域名称.键名}:从指定域中获取指定键的值
* 域名称:
1. pageScope --> 从pageContext对象中获取值
2. requestScope --> 从request对象中获取值
3. sessionScope --> 从session对象中获取值
4. applicationScope --> 从application(ServletContext)对象中获取值
* 举例:在request域中存储了name=张三
获取张三:${requestScope.name}
2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
你写了${name}它就会从pageScope中找键为name的,找不到就继续在requestScope中找,,,找到为止
3. 获取对象、List集合、Map集合的值
1. 获取对象:${域名称.键名.属性名}
* 本质上会去调用对象的getter方法
2. 获取List集合:${域名称.键名[索引]}
3. 获取Map集合:
* ${域名称.键名.key名称}
* ${域名称.键名["key名称"]}
3. 隐式对象:
* el表达式中有11个隐式对象
* pageContext:
* 获取jsp其他八个内置对象
* ${pageContext.request.contextPath}:动态获取虚拟目录
忽略el表达式

运算符:

获取值(重点)


获取对象(重点)
对象的属性是是什么?请参考Day04_用户登录案例的“11.关于BeanUtils”


<%@ page import="cn.itcast.domain.User" %>
<%@ page import="java.util.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取数据</title>
</head>
<body>
<%
User user = new User();
user.setName("张三");
user.setAge(23);
user.setBirthday(new Date());
request.setAttribute("u",user);
%>
<h3>el获取对象中的值</h3>
${requestScope.u}<br> //这句代码只能获取到u的地址值,要想获取到值必须通过对象的属性获取
//通过的是对象的属性来获取
${requestScope.u.name}<br> //requestScope.u就是找request域中有没有一个u的键,找到它对应的对象,然后通过这个对象调用getname方法获取name值
${u.age}<br>
${u.birthday}<br>
${u.birthday.month}<br> //这是美国的日期,美国的3月就是我们的4月,那么如果你想获取中国的日期格式怎么办呢?
${u.birStr}<br> //必须有一个自己写的getBirStr()方法,要不然会报错
</body>
</html>
获取list集合、map集合的值(重点)

空运算符

隐式对象

十四、JSTL
1. 概念:JavaServer Pages Tag Library JSP标准标签库
*用于简化和替换jsp页面上的java代码
2. 使用步骤:
1. 导入jstl相关jar包
2. 引入标签库:taglib指令: <%@ taglib %>
3. 使用标签
3. 常用的JSTL标签(今天只学习三个)
1. if:相当于java代码的if语句
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:
* c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
2. choose:相当于java代码的switch语句
1. 使用choose标签声明 相当于switch声明
2. 使用when标签做判断 相当于case
3. 使用otherwise标签做其他情况的声明 相当于default
3. foreach:相当于java代码的for语句
1. 完成重复的操作
for(int i = 0; i < 10; i ++){
}
* 属性:
begin:开始值。
end:结束值。
var:临时变量。
step:步长。
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
例如:<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
</c:forEach>
2. 遍历容器
List<User> list;
for(User user : list){
}
* 属性:
items:容器对象
var:容器中元素的临时变量
varStatus:循环状态对象
index:容器中元素的索引,从0开始
count:循环次数,从1开始
例如:<c:forEach items="${list}" var="str" varStatus="s">
</c:forEach>
if标签

choose标签

foreeach标签

JSTL小练习
需求:在request域中有一个存有User对象的List集合。需要使用jstl+el将list集合数据展示到jsp页面的表格table中
表格中如果是奇数行就让它是绿色,如果是偶数行就让他是红色


十五、三层架构:软件设计架构
1. 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
2. 业务逻辑层:处理业务逻辑的。
3. 数据访问层:操作数据存储文件。

十六、用户信息列表展示
这个案例相当重要,它综合了所有知识。
感谢浏览和收藏
712

被折叠的 条评论
为什么被折叠?



