#jsp简介
sun公司制订的一种服务器端动态页面技术规范。
- 因为直接使用servlet虽然也可以生成动态页面,但是过于繁琐(需要使用out.println),并且不利于维护(如果要修改页面,需要修改java代码),所以,sun才制订了jsp技术规范。
- jsp是一个以.jsp为后缀的文件(主要由html和java代码构成),容器会将该文件转换成一个对应的servlet然后执行。
- JSP本质上就是Servlet
#jsp编写规范
step1. 添加一个以.jsp为后缀的文件。
step2. 在该文件里面,可以添加如下内容
- 注释
html注释:<!-- 内容-->
如果注释中的内容包含Java代码,这些代码会被执行
jsp注释:<%- - 内容 - -%>注释内的Java代码不会被执行
- html /css/js :直接写。
- Java代码写法
- JSP表达式:<%=…%>
合法内容包括:变量、变量加运算符组合的表达式、有返回值得方法 - JAVA代码片段:<%…%>
能够写在方法里的Java代码片段都可以作为其内容 - JSP声明:<%!..%>
作用是声明成员属性或成员方法(作为转换成servlet的成员) - JSP页面中的指令:<%@指令名 属性=值 %>
- 常用指令
- page指令
- import引入包:
<%@ page import="bean.*" %>
- contentType设置生成的HTML类型
- pageEncoding设置当前JSP的编码
- import引入包:
- include指令
在JSP页面转译成Servlet时,能够将其他文件包含进来。可以包含JSP文件,也可以是静态的HTML文件比如每个JSP页面的导航栏、版权声明、logo等都可以抽出到单个JSP文件中,然后每个页面include即可
语法:<%@ include file="url" %>
- page指令
- taglib指令用于引入JSTL标签
作用:控制JSP在转译成Servlet类时生成的内容
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
//c是别名,jstl.jar->META-INF->c.tld,可以查看核心包uri.
#隐含对象
也叫JSP内置对象,由Tomcat自动创建
在JSP文件中可以直接使用的对象,一共有9个。
1.request:类型是HttpServletRequest,同Servlet
2. response:类型是HttpServletResponse,很少用,因为JSP会自动响应
3. out:类型是JSPWriter(同PrintWriter)
4. config:类型ServletConfig
<body style="font-size:30px;">
公司:<%=config.getInitParameter("company") %>
</body>
5.application:类型是ServletContext
<body style="font-size:30px;">
当前系统在线人数是:
<%=application.getAttribute("count") %>
</body>
6.exception:类型是Throwable
指的是当前页面的异常,当发生异常时才能用
- 一个页面抛异常
<%@page pageEncoding="utf-8" contentType="text/html; charset=utf-8"
errorPage="a6.jsp" %>
<html>
<head></head>
<body style="font-size:30px;">
<%
Integer.parseInt("123a");
%>
</body>
</html>
- 一个页面响应
<%@page pageEncoding="utf-8" contentType="text/html; charset=utf-8"
isErrorPage="true"%>
<html>
<head></head>
<body style="font-size:30px;">
<%=exception.getMessage()%>
</body>
</html>
7.session:HttpSession
<body style="font-size:30px;">
<%=session.getId()%>
</body>
8.page:类型是Object,指代当前的JSP,相当于this(基本不用)
9.pageContext:类型就是PageContext,用于给页面提供数据。该对象中引用了其他8个隐含对象,可以通过它获取其他对象
<body style="font-size:30px;">
<%
pageContext.setAttribute("username", "Sally");
%>
username:<%=pageContext.getAttribute("username") %>
</body>
#jsp执行过程
step1. 容器要将jsp文件先转换成一个servlet(.jsp文件 —>.java文件)
html(css,javascript) service方法里面,使用out.write输出。
<% %> service方法里面,照搬。
<%= %> service方法里面,使用out.print输出。
step2. 容器调用该servlet。
#转发
##什么是转发?
一个web组件将未完成的任务交给另外一个web组件继续做。 转发的本质: 一个web组件通知容器去调用另外一个web组件。
- web组件,指的是servlet或者jsp。
- 一个servlet将数据转发给一个jsp,由jsp将数据以合适的方式展现出来。
##如何转发?
-
step1.将数据绑订到request。
request.setAttribute(String name,Object obj);
Object request.getAttribute(String name); -
step2.获得转发器。
RequestDispatcher rd = request.getRequestDispatcher(String url);
url转发的目的地。 -
step3.转发
rd.forward(request,response);
##特点
-
转发之后,浏览器地址栏的地址是不变的。
-
转发目的地有限制(要求是同一个应用)。
#比较:转发与重定向
(1)能否共享request,转发可以,而重定向不行。
request和response的生存时间很短暂(一次请求和响应期间存在)。
(2)目的地有无限制,转发有限制(同一个应用),而重定向没有限制。
(3)浏览器地址栏的地址有无变化,转发没有变化,而重定向有变化。
#相对路径和绝对路径
-
哪里需要使用路径
- 链接地址
<a href="url" ></a>
- 表单提交
<form action="url">
- 重定向response.sendRedirect(url)
- 转发request.getRequestDispatcher(url)
- 链接地址
-
相对路径 :相对路径不以"/"开头的路径。
-
绝对路径:绝对路径:以"/"开头的路径
-
固定位置
-
链接地址,表单提交,重定向的固定位置是项目部署名
-
转发的固定位置是部署名之后的位置
-
获取应用的实际部署名
request.getContextPath()
#状态管理
HTTP是一次请求一次连接,下次请求时,服务器不认识这个客户端,该请求方式叫做无状态协议。将浏览器与web服务器之间多次交互当做一个整体来处理,并且 将多次交互所涉及的数据(即状态)保存下来。
- 状态管理两种方式
- 将状态保存在客户端(浏览器) :Cookie
- 将状态保存在服务器端 :session
#Cookie
服务器临时存放在浏览器端的少量数据
##工作原理
当浏览器访问服务器时,服务器会将少量数据发送给浏览器
(使用set-cookie消息头),浏览器会将这些数据临时保存下来;
当浏览器再次访问服务器时,会将之前保存的数据发送给服务器
(使用cookie消息头)。
##添加cookie
Cookie c = new Cookie(String name,String value);
response.addCookie(c);
##读取cookie
Cookie[] request.getCookies();
注:有可能返回null。
String cookie.getName();
String cookie.getValue();
##编码问题
- cookie只能保存合法的ascii字符,如果是中文,
需要将中文转换成合法的ascii字符串。
String URLEncoder.encode(String str,String charset);
String URLDecoder.decode(String str,String charset);
- 建议添加cookie时,都统一编码。
##生存时间问题
- 默认情况下,浏览器会将cookie保存在内存里面。只有浏览器不关闭,cookie就会一直保存,浏览器一关闭,cookie就会被删除。
- 设置时间
cookie.setMaxAge(int seconds)
:b1. seconds单位是秒。 - b2. 当seconds > 0时,浏览器会将cookie保存在硬盘上(文件的形式存放),超过指定时间,浏览器会销毁该cookie。
- 当seconds < 0时,默认值(即保存在内存里面)。
- 当seconds = 0时,删除cookie。
- 要删除一个名称为username的cookie:
Cookie c = new Cookie("username","");
c.setMaxAge(0);
response.addCookie(c);
##cookie的路径问题
- 浏览器访问服务器时,会比较cookie的路径是否与要访问的路径匹配,只有匹配的cookie才会被发送。
- cookie的默认路径
默认等于添加该cookie的web组件的路径。
比如 /servlet-day06/biz01/addCookie.jsp添加了
一个cookie,则该cookie的默认路径就是
/servlet-day06/biz01 - 匹配规则
要访问的路径必须等于cookie的路径或者是其子路径,符合该要求的cookie才会被发送出去。比如,cookie的路径是 /servlet-day06/biz01,
则:
/servlet-day06/findCookie1.jsp 不会
/servlet-day06/biz01/findCookie2.jsp 会
/servlet-day06/biz01/sub/findCookie3.jsp 会
d.cookie.setPath(String path) //设置cookie的路径
##cookie的限制
a.可以被用户禁止。
b.只能保存少量的数据(大约4k左右)。
c.保存的数量也有限制(大约几百个)。
d.只能保存字符串,对于中文,需要编码。
e.不安全。
#Session(会话)
服务器端为保存状态而创建的一个特殊的对象。
##工作原理
浏览器访问web服务器时,服务器会为每一个浏览器在服务器端的内存中分配空间,单独创建一个session对象,该对象有一个Id属性,其值唯一,一般称之为SessionId。并且服务器会将这个SessionId(使用Cookie的方式)发送给浏览器;浏览器再次访问服务器时,会将SessionId发送给服务器,服务器可以依据SessionId找到对应的Session对象
##获取session对象
- HttpSession s = request.getSession(boolean flag);
- flag为true时
先查看请求当中有没有sessionId,如果没有,则创建ession对象;如果有sessionId,则依据该sessionId去查找对应的session对象(如果找到了,则返回,找不到,则创建一个新的session对象)。 - flag为false时
先查看请求当中有没有sessionId,如果没有,返回null;如果有sessionId,则依据该sessionId去查找对应的session对象(如果找到了,则返回,找不到,返回null)。 - HttpSession s = request.getSession();等价于request.getSession(true);
- 绑订数据相关的几个方法
session.setAttribute(String name,Object obj)
Object session.getAttribute(String name);
removeAttribute(String name);
##优缺点
- 优点
数据不能被篡改,安全
Session能够保存的数据类型更丰富,Cookie只能保存字符串
Session能够保存更多的数据,Cookie大约保存4k - 缺点
服务器压力大针对此问题,tomcat会做一些处理
对于长时间没有响应,但未超时的session,tomcat会将其存储到硬盘上,以释放内存压力。称为钝化
##URL重写
如果浏览器禁用Cookie,Session就不能使用。但可以通过URL重写来解决
原因
Session会使用Cookie的方式将SessionId发送给浏览器,如果禁止Cookie,则浏览器就不会保存SessionId
什么是URL重写
浏览器在访问服务器上的某个地址时,不再使用原来的那个地址,而是使用经过改写的地址(即,在原来的地址后面加上了SessionId)
实现URL重写
如果是链接地址和表单提交
response.encodeURL(String url)
如果是重定向
response.encodeRedirectURL(String url)
##session超时
服务器会将空间时间过长的session对象删除掉。session默认的超时时间限制是30分钟,可以修改服务器缺省的超时时间限制
<session-config>
<session-timeout>30</session-timeout>
</session-config>
-
设置超时时间:session.setMaxInactiveInterval(int seconds)
-
删除session:session.invalidate()
##session验证 -
step1.登录成功之后,在session对象上绑订一些数据,比如
session.setAttribute(“user”,user); -
step2.当用户访问需要保护的资源的时候(只有登录成功才能访问的资源)
Object obj = session.getAttribute("user");
if(obj == null){
//没有登录
response.sendRedirect("login.jsp");
}
##session应用:验证码
- 生成验证码
public class CheckcodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void service(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
System.out.println(
"CheckcodeServlet's service()");
/*
* step1. 绘图
*
*/
//先创建一个画布(内存映像对象)
BufferedImage image =
new BufferedImage(80,30,
BufferedImage.TYPE_INT_RGB);
//获得画笔
Graphics g = image.getGraphics();
//给画笔设置颜色
g.setColor(new Color(255,255,255));
//给画布设置背景颜色(即给画布上色)
g.fillRect(0, 0, 80, 30);
//给画笔设置颜色
Random r = new Random();
g.setColor(new Color(r.nextInt(255),
r.nextInt(255),r.nextInt(255)));
//设置字体 (字体,风格,大小)
g.setFont(new Font(null,
Font.BOLD|Font.ITALIC,24));
//在画布上绘图
String number = getNumber(5);
System.out.println("number:" + number);
g.drawString(number, 1, 25);
//加一些干扰线
for(int i = 0; i < 8; i ++){
g.setColor(new Color(r.nextInt(255),
r.nextInt(255),r.nextInt(255)));
g.drawLine(r.nextInt(80), r.nextInt(30),
r.nextInt(80), r.nextInt(30));
}
/*
* step2.将图片压缩,然后输出
*/
//设置content-type
response.setContentType("image/jpeg");
//获得字节输出流(图片是二进制数据)
OutputStream os =
response.getOutputStream();
//将原始图片(image)按照指定的算法压缩(jpeg),
//然后将压缩之后得到的字节写入response对象。
javax.imageio.ImageIO.write(
image, "jpeg", os);
os.close();
}
/*
* 生成一个长度固定为size个字符,并且这些字符要求从
(A~Z,0~9)中随机选取,比如 X09BD
*/
private String getNumber(int size) {
Random r = new Random();
String number = "";
String chars = "ABCDEFGHIJKLMNOPQRS"
+ "TUVWXYZ0123456789";
for(int i = 0; i < size; i ++){
number += chars.charAt(
r.nextInt(chars.length()));
}
return number;
}
}
- 使用
//将验证码图片和字符串存入 Session 对象:
private void createImage(HttpServletRequest req, HttpServletResponse res) throws IOException{
Object[] obj=ImageUtil.createImage();
//将验证码存入 session HttpSession session=req.getSession();
session.setAttribute("imagecode", obj[0]);
//将图片输出给浏览器
BufferedImage image=(BufferedImage)obj[1]; res.setContentType("image/png"); OutputStream os=res.getOutputStream(); ImageIO.write(image, "png", os);
os.close();
}
在 JSP 中显示验证码图片:
<tr>
<td class="login_info">验证码:</td>
<td class="width70"><input name="code" type="text" class="width70" /></td>
<td><img src="createImage.do" alt="验证码" title="点击更换" onclick="this.src='createImage.do?x='+Math.random()"/></td>
<td><span class="required">${error }</span></td>
</tr>
#MVC设计思想
是一个经典的设计思想,可以将代码分为以下3层
- M(Model):业务组件,用来处理业务
- V(View):视图组件,用来显示数据
- C(Controller):控制器,用来处理请求,控制业务的流转
对代码进行分层,从而对代码解耦,降低耦合度,便于团队开发和维护
#JavaBean
- 满足如下规范的类
必须有包
必须有默认构造器
必须实现序列化接口
通常有get, set方法