目录
JSP运行原理 |
- 每当有JSP页面访问请求WEB容器时,容器将该访问请求交给JSP引擎取处理,Tomcat的JSP引擎就是一个servlet程序,它负责解释和执行JSP页面
- 每个JSP页面在第一次被访问时,JSP引擎先将它翻译成一个Servlet源程序,接着再编译成Servlet的class文件,然后再由WEB容器装载和解释执行这个由JSP页面翻译成的Servlet程序
JSP执行过程 |
执行JSP文件需要经过两个时期:
转译时期
和请求时期
;
转译时期
:JSP转译成Servlet类(.class文件)
请求时期
:Servlet类执行后,将结果响应至客户端
- 客户端发出请求
- Web容器将JSP转译成Servlet源码
- Web容器将产生的源码进行编译
- Web容器加载编译后的代码并执行
- 将执行结果响应至客户端
JSP九大内置对象 |
序号 | 内置对象 | 类型 |
---|---|---|
1 | request | javax.servlet.http.HttpServletRequest |
2 | response | javax.servlet.http.HttpServletResponse |
3 | session | javax.servlet.http.HttpSession |
4 | pageContext | javax.servlet.jsp.PageContext |
5 | application | javax.servlet.ServletContext |
6 | config | javax.servlet.ServletConfig |
7 | out | javax.servlet.jsp.JspWriter |
8 | page | java.lang.Object |
9 | exception | java.lang.Throwable |
request常用方法 |
- 获取客户端信息,例如请求URL、主机IP、资源等
- 获取客户端请求头信息
- 获取客户端请求参数
解决提交数据中文乱码
问题:
- 提交方式为get,设置request对象编码是无效的,request对象还是以ISO8859-1编码接收数据,需要做转换
String data = request.getParameter("paramName");
byte[] source = data.getBytes("ISO8859-1");
data = new String(source, "UTF-8");
- 提交方式为post,只需在服务端设置request对象编码即可,设置成和客户端提交一样的编码就行
request.setCharacterEncoding("UTF-8");
request对象实现请求转发
:
请求转发
:指一个web资源收到客户端请求后,通知服务器区去调用另外一个web资源进行处理
实现请求转发
的两种方式:
- 通过ServletContext的getRequestDispatcher(“path”),该方法返回一个RequestDispatcher对象,调用forward方法实现请求转发
- 通过request提供的getRequestDispatcher(“path”),该方法返回一个RequestDispatcer对象,调用forward方法实现请求转发
请求重定向和请求转发的区别:
- 一个web资源收到客户端请求之后,通知服务器取调用另外一个web资源进行处理,是服务器行为,一次request,称为
请求转发
- 一个web资源收到客户端请求之后,通知服务器取访问另外一个web资源进行处理,是客户端行为,两次request,称为
请求重定向
解释:
背景:办理营业执照
重定向
:你先去了A局,A局看了之后,说:“这个不归我们管,去B局”,然后你转车去了B局
转发
:你先去了A局,A局看了之后,知道这个事情由B局管,但是没有把你叫去B局,而是叫你等一下,然后联系了B局的人,让他们把事情办好后,送过来
response常用方法 |
web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代替请求的
request
对象和代表响应的response
对象,request
获取客户端提交的数据,response
向客户端输出数据
- 负责向客户端发送数据的相关方法
- 负责向客户端发送响应头的相关方法
- 负责向客户端发送状态码的相关方法
- 响应状态码的常量
常见应用
- 使用OutputStream流向客户端浏览器输出中文数据
String str = "中国";
OutputStream outputStream = response.getOutputStream(); // 获取OutputStream输出流
response.setHeader("content-type", "text/html;charset=UTF-8"); // 通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
byte[] dataByteArr = str.getBytes("UTF-8"); // 将字符转换成字节数组,指定以UTF-8编码进行转换
47 outputStream.write(dataByteArr); // 使用OutputStream流向客户端输出字节数组
- 使用PrintWriter流向客户端浏览器输出中文数据
String str = "我爱你";
response.setCharacterEncoding("UTF-8"); // 设置将字符以"UTF-8"编码输出到客户端浏览器
PrintWriter out = response.getWriter(); // 获取PrintWriter输出流
out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
out.write(data);//使用PrintWriter流向客户端输出字符
- 实现文件下载
- 获取要下载文件的绝对路径
- 获取要下载的文件名
- 设置content-disposition响应头控制浏览器以下载的形式打开文件
- 获取要下载的文件输出流
- 创建缓冲区
- 通过response对象获取OutputStream流
- 将FileInputStream流写入buffer缓冲区
- 使用OutputStream将缓冲流的数据输出到客户端
String realPath = this.getServletContext().getRealPath("/download/张家界国家森林公园.JPG"); // 获取要下载的文件的绝对路径
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1); // 获取要下载的文件名
// 设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
InputStream in = new FileInputStream(realPath); // 获取文件输入流
// 使用PrintWriter流下载文件
// FileReader in = new FileReader(realPath);
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
// PrintWriter out = response.getWriter();
while ((len = in.read(buffer)) > 0) {
out.write(buffer,0,len); // 将缓冲区的数据输出到客户端浏览器
}
in.close();
分析:使用PrintWriter流处理字节数据,会导致丢失,下载文件时要使用OutputStream流,OutputStream是字节流,可以处理任意类型的数据,而PrintWriter是字符流,只处理字符数据
生成随机图片作为验证码
主要使用BufferedImage类设置http响应头控制浏览器禁止缓存当前内容
response.setDataHeader("express", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
设置http响应头控制浏览器定时刷新网页
response.setHeader("refresh", "5"); // 控制浏览器每隔5秒刷新一次
实现请求重定向
应用场景:用户登录界面,登录成功后,跳转指定界面,这个过程就是重定向
实现方式:
response.sendRedirect(String path);
servlet
:生命周期:
- 初始化,调用init()方法
- 响应客户端请求,调用service()方法(doGet/doPost)
- 终止阶段:调用destroy()方法
session常用方法 |
会话概念:用户开一个浏览器,点击多个超链接,访问web资源,然后关闭浏览器,整个过程称为会话;有状态会话:能记住某人曾经访问过
会话可以解决的问题:保存用户数据
保存会话的两种技术:
Cookie
:客户端技术,程序把每个用户数据以cookie的形式写给用户各自浏览器,当用户使用浏览器再去访问服务器的web资源时,就会带着各自的数据去
Seession
:是服务端技术,服务器可以为每个用户的浏览器创建一个其独享的session对象,多那个用户去访问服务器中的其它web资源时,其它资源再从用户名各自的session中取出数据为用户服务
cookie
使用范例:
// 设置服务端以UTF-8编码进行输出
response.setCharacterEncoding("UTF-8");
//设置浏览器以UTF-8编码进行接收,解决中文乱码问题
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
// 获取浏览器访问服务器传递过来的cookie数组
Cookie[] cookies = request.getCookies();
// 如果用户是第一次访问,那么得到的cookies将是null
if (null != cookies) {
out.write("上次的访问时间是:");
// out.write(URLDecoder.decode(cookies[i].getValue(), "UTF-8")); 显示中文,要进行解码操作
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if ("lastAccessTime".equals(cookie.getName())) {
Long lsatAccessTime = Long.parseLong(cookie.getValue());
Date date = new Date(lsatAccessTime);
out.write(date.toLocaleString());
}
}
} else {
out.write("第一次访问本站");
}
// 用户访问过后重新设置访问时间,存储cookie中,然后发送到客户端浏览器
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis() + ""); // 新建一个cookie
// Cookie cookie1 = new Cookie("userName", URLEncoder.encode("中国", "utf-8")); 中文显示
// 设置cookie的有效期为1天,如果未设置有效期,关闭浏览器之后就失效了,设置有效期,在关闭浏览器之后仍然有效,如设置有效期为0,则为删除cookie的操作
cookie.setMaxAge(24 * 60 * 60);
// 将cookie对象添加到response对象中,这样服务器在输出response对象中的内容时就会把cookie也输出到客户端
response.addCookie(cookie);
Session简介:
session和cookie的区别
- cookie是吧用户的数据写给用户浏览器
- session是吧数据写到用户独占的session中
- session对象由服务器创建,开发人员可使用request对象的getSession方法得到session对象
session 实现原理
服务器创建session之后,会把session的id号,以cookie的形式回写给客户端,只要客户端浏览器不关,再次访问服务器时,都会带着session的id号去,服务器发现客户端带session的id过来,就会使用内存中与之对应的session为之服务
session 创建
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 使用request对象的getSession()获取session,如果不存在就创建一个
HttpSession session = request.getSession();
// 将数据存储到session中
session.setAttribute("str", "中国");
// 获取session的id
String sessionId = session.getId();
// 判断session是不是新建的
if (session.isNew()) {
response.getWriter().print("session创建成功,sessionId是:" + sessionId);
} else {
response.getWriter().print("服务器已存在该session, session的id是:" + sessionId);
}
session销毁
自动销毁:默认情况下30分钟不使用
人工销毁:
- 在web.xml中
<session-config>
<session-timeout>15</session-timeout> // 设置有效时间,单位为:分钟
</session-config>
- 在程序中
session.invalidate();
浏览器禁用cookie之后session处理
解决方案:URL重写
response.encodeRedirectURL(String url); // 用于对sendRedirect方法后的url地址进行重写
response.encodeURL(Stirng url); // 用于对表单action和超链接的url地址进行重写
application常用方法 |
application 对象用来在多个程序或者是多个用户之间共享数据,服务器一旦启动就会自动创建application对象,并一直保持下去,直至服务器关闭,application会自动消失,不需要麻烦垃圾回收机制。
servlet三大域对象
request
:一个用户可以有多个session
:一个用户就一个application(ServletContext)
:servletContext所有用户公用一个,要考虑到线程安全问题
application
以一个网站的访问量来演示application的用法:
未使用application对象
// 直接在方法上加synchronized关键字,放置资源竞争
int countor = 0; // 初始化计数器
countor++; // 计数器自增
运行效果:每刷新一次页面,计数器加1,正常逻辑是有新用户访问网站,计数器进行加1操作,而不是刷新页面一次就为一次访问
加入application对象
protected synchronized void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext application = this.getServletContext(); // 获取servletContext对象
Integer number = (Integer)application.getAttribute("Count");
if(null == number) {
number = new Integer(1); // 实例化number对象
application.setAttribute("Count", number);
} else {
number=new Integer(number.intValue()+1);
application.setAttribute("Count", number);
}
Integer numberCount = (Integer)application.getAttribute("Count");
application.setAttribute("number", numberCount);
response.sendRedirect("/applicationtest.jsp");
}
前台页面:applicationtest.jsp
<body>
欢迎访问本站,你是第${number }个访问用户
</body>
运行效果:刷新当前页面,计数器并不会做自增操作,只有重新访问这个页面之后,才会进行加1操作
pageContext常用方法 |
四大容器
容器 | 作用域 |
---|---|
pageContext | 仅仅是当前页面,无法传参 |
request | 当前页面,可以传参 |
session | 同一个SESSIONID共用一个 |
application | 只要服务器没有重新启动,就一直存在 |
pageContext对象时JSP技术中最重要的一个对象,它代表JSP页面的运行环境,代表页面上下文,主要用于访问JSP之间的共享数据,不仅封装了8大隐式对象的引用,自身还是一个域对象,可以用来存储数据,可以操作另外三个域(request,session,servletContext)
获得其它对象
getRequest()方法返回request隐式对象
getResponse()方法返回response隐式对象
getSession()方法返回session隐式对象
getServletContext()方法返回application隐式对象
getServletConfig()方法返回config隐式对象
getOut()方法返回会out隐式对象
getPage()方法返回page隐式对象
getException()方法返回exception隐式对象
pageContext对象封装了访问其他域的方法
代表各个域的常量
- PageContext.APPLICATION_SCOPE
- PageContext.SESSION_SCOPE
- PageContext.REQUEST_SCOPE
- PageContext.PAGE_SCOPE
例如:
pageContext.getAttribute("name", PageContext.SESSION_SCOPE);
PageContext跳转到其它资源
pageContext.getRequest().getRequestDispatcher("/index.jsp").forward(request, response);
config常用方法 |
config代表当前JSP的配置信息,到那时JSP页面通常无需配置,也就不存在配置信息,比较少用,但是在Servlet则是用处相对较大
out常用方法 |
- out对象用于向客户端发送文本数据
- out对象通过调用pageContext对象的getOut()方法返回
- JSP页面中的out对象类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小
page常用方法 |
page对象表示当前一个JSP页面,可以理解为一个对象本身
exception常用方法 |
exception对象是一个异常对象,当页面在存储过程中发生了异常,就产生这个对象,如果JSP页面应用此对象,必须把isErrorPage设置成true
通常用法
- exception.getMessage() 返回描述异常消息
- exception.toString() 返回关于异常的简短描述消息
- exception.printStackTrace() 显示异常及其栈轨迹