Jsp:Java Server Pages
http://127.0.0.1:8080/weba/hello.html
Tomcat执行过程:
浏览器通过http协议发送请求,以TCP协议作为底层,去tomcat的安装目录下找到webapps下的weba文件夹,再继续找到hello.html.
http协议有协议头和协议头,底层是TCP,是无状态的,两次连接。
127.0.0.1:找到服务器的IP地址
8080:根据端口号找到服务的指定应用 Tomcat,tomcat是一个中间件
访问结果通过response返回,静态代码tomcat不执行,java代码tomcat执行,执行后tomcat把执行结果嵌入到静态代码html中,由浏览器同一执行并且显示结果。
通过虚目录:context 设置
服务器先启动,浏览器发请求
Tomcat的目录结构:
bin:tomcat的启动和关闭信息
webapps:项目目录存放,
conf:server.xml,虚目录配置文件
log:存放日志文件
lib:jar包 j2ee jar包 和类库
work:存放生成的class字节码文件(临时文件)
web目录结构:
webapps-
WEB-INF
web.xml:部署文件
配置虚目录:(目的:安全性《名字 位置 存储》)
配置文件的路径webappsàconf-àserver.xml
<Context path=”/test” docBase=”f:\weba” />
path:虚拟访问路径
docBase:项目的真实访问路径
一个项目名可以配置多个虚目录名,但是一个虚目录名只能对应一个项目
表单数据存储在服务器,由浏览器执行。
Tomcat在执行jsp时,静态代码不会执行,会执行java代码。不同的java代码有不同的执行形式。
Web组件不能独立于web项目。不能直接把.jsp文件放在webapps下去执行。
Jsp是动态组件,服务器执行
标签包含:如果被包含页面是html静态页面,先包含不执行
tomcat执行.jsp文件的过程:先将.jsp文件变成.java文件,再编译为字节码文件hello.jspà hello-jsp.java 经过编译后变成 hello-jsp.class。虚拟机执行java代码,执行完的结果嵌入静态代码中
修改.jsp文件时,可能出现修改不成功,将tomcat目录下的work文件夹删掉,并且重启tomcat。
Servlet:需要自己手动先变成字节码文件,再让tomcat执行。
Jsp=静态代码+动态代码
静态代码放在服务端,由客户端执行。
注释:
静态注释:对静态代码的注释,<!—服务器不会执行,浏览器来执行-- >
动态注释:对动态代码的注释,<%--里面对el表达式,指令,标签,java代码进行注释 ,tomcat会执行,但是不会发给浏览器 --%>
对于原生的java代码,可以使用java中的注释 《 //aa /*aa */ /**aa */ 》
在配置文件中,配置信息被静态注释时 ,被静态注释的配置信息还是由服务器执行。
行为:表示实际在操作一些事(实际代码完成操作)
思想:是在告诉你怎么做一件事情(配置信息是一种思想,为了指挥tomcat怎么做)
服务器中的配置信息由服务器解析。
Jsp变量
全局变量 :<%! int i=0; %>//i为全局变量,只初始化一次(相当于java中的实例全局变量)
局部变量:<% int i=0;%>//i 为局部变量,没有 !号便是局部变量。
方法中的变量一般没有访问权限,都使用默认的。方法中的局部变量使用前需要初始化,因为它没有默认初始,构造方法也不能为它初始化,否则会发生编译错误。
Jsp中可以定义类,方法,变量,但是不推荐使用。<% %>//就在里面定义
表达式:
<%=i++ %>//使用response内置对象 ,jsp语法
特点:安全,简单,response自动将代码送回,一般只使用在jsp页面中(推荐使用response),发送完数据到浏览器就自动销毁。
<% out.println(i++);%>//使用out内置对象 ,java语法
特点:在任何组件和页面上都能取到out内置对象,就能使用。不安全,out可能会跟回浏览器。
打印99乘法表:
<table border=”1”>
<% for(int i=1;i<10;i++){ %>
<tr>
<% for(int j=1;j<i+1;j++){ %>
<td><%=i*j %></td>
<% } %>
</tr>
<% } %>
</table>
练习:写个下三角的99乘法表(指定行和列数的乘法表)
Jsp如何接收用户请求
表单代码由浏览器解析
Get请求:会在访问地址栏上显示输入的参数
Post请求:安全,输入的参数不会在地址栏上显示
服务器不关心请求的来源,因为表单最终也会变成 地址栏协议请求格式。
Request接收请求参数:
request.getParameter(“rownum”);
request.getParameter(“colnum”);
指令:
page:指定当前监听页面的处理方式,导包
静态编码:
<%@ page contentType=”text/html; charset=gb2312” %>
用page做静态编码只能有一条,导包可以有多条。
Tomcat发现接收的是html文件,就算里面有java代码,tomcat也不会执行,会直接发给浏览器。
Jsp:真正的作用 : 拿到结果并且进行处理,把结果通过response放在http协议中发到浏览器。(用户看到的结果是由浏览器显示的)
Response:可以和浏览器建立信道(浏览器底层是TCP协议),把结果数据发送到浏览器。
Jsp:语法包括注释,变量,语法。
使用表单和用户做交互。
GET:
http://127.0.0.1:8080/table/printTable.jsp?rownum=2&colnum=4
POST:
http://127.0.0.1:8080/table/printTable.jsp
pageEncoding:jsp本身的编码
charset:服务器发送给客户端的内容的编码
include指令:(包含) 静态包含
<%@include file=”hello.jsp” %>
先找到被包含页面,把该页面内容全部包含到当前页面中。
特点:先包含再执行,不识别被包含页面的类型。
要求:被包含页面不能有<html><body>,被包含页面不能和当前页面重复定义变量
request.getParameter(“param”);//当没有param参数时,返回的结果为 null
<jsp:include page=””>标签包含:动态包含
<jsp:include page=”hello.jsp”>
标签是java一行或者多行代码的标识,通过标识找到java代码再去执行,标签包含属于java语法范畴
找到被包含页面,然后执行,最后把执行的结果包含到当前页面中
特点:识别被包含页面类型
包含标签中如果有子标签,会先执行子标签中的内容再执行包含标签。
<jsp:param name=”ref” value=”ZTE”/>:执行此标签的意思是往该页面中对应的request内置对象中设置一个参数名为ref的参数,参数值为ZTE。
如果被包含页面是动态页面,就先执行再包含,当前页面通过子标签可以向被包含页面传递参数。通过request内置对象传递。
如果被包含页面是静态页面,就只包含不执行
主要缺点:被包含页面最好是不要是静态页面,静态页面中最好不要有动态代码
什么时候请求结束?
1、 此页面确实已经执行完
2、 此页面执行完,response要和浏览器建立信道,把结果数据放在信道上
|
标签包含 |
指令包含 |
|
共同点 |
把一个页面包含到当前页面中 |
||
语法 |
标签包含属于java语法 |
指令包含属于jsp语法 |
|
写法 |
<jsp:include page=””/> |
<%@include file=””%> |
|
是否识别文件类型 |
标签包含识别被包含文件类型 |
指令包含不识别类型 |
|
传参 |
动态页面可以传递参数,如果被包含的为静态页面则不能传参。 |
指令包含不能传递参数 |
|
包含与执行顺序 |
标签包含如果包含的为动态页面先执行后包含,如果为静态页面就只包含不执行 |
指令包含先包含后执行 |
|
缺点 |
包含静态页面时不能执行 |
不能有<html><body>,不能重复定义变量 |
|
总结 |
一般页面都写成jsp页面,然后使用标签包含(jsp:include) |
||
跳转:
服务端跳转:<jsp:forward page=””/>
用户只发一次请求,地址栏不改变,
只创建一个request内置对象,服务端跳转的各个组件和页面都能共享此request。
优点:安全,地址栏不改变,只发一次请求
1、<jsp:forward page=””/>
2、pageContext.forward();
3、 request.getRequestDispatcher("1.jsp").forward(request,response);
3、服务器端跳转“/”代表站点根路径
客户端跳转:response.sendRedirect(“”);
用户发多次请求,地址栏改变
每发一次请求会创建一个request内置对象,所以request不能用来传递参数。
请求都从客户端发出
1、链接跳转:<a href=””></a>
2、表单提交
3、Response.sendRedirect(“3.jsp”);
4、<mata http-equiv=”refresh”, content=”3;2.jsp”/>
5、response.setHeader(“refresh”,” 3;2.jsp”);
6、客户端跳转“/”代表服务器跟路径webapps
内置对象
为什么要用内置对象?(用来传递数据)
Tomcat为了接受用户请求自动创建的完成用户组件之间的数据交互和传递。
内置对象由tomcat自动创建。
九大内置对象:
request:用户一发请求时就创建,请求结束就销毁。传递数据(服务端跳转才能传递数据),用户请求参数只放在request内置对象中。作用域为 request
response: 用户一发请求时就创建,请求结束就销毁。将结果数据交给浏览器显示。作用域为page
pageContext:用户发请求访问jsp页面时创建,离开页面时就销毁。存放临时数据。作用域为page。
session:当用户第一次访问服务器动态组件时创建,用户下线15分钟后就销毁,或者使用invalidate()。作用:存放验证信息,客户端跳转。作用域为session.
application:服务器启动时创建,服务器关闭时销毁。只创建一个,公用的。作用域为application.
out:response创建,作用域为page.
config: 服务器启动时创建,创建一个。存放配置信息的初始化参数。作用域为page.
page: 用户发请求访问jsp页面时创建,离开页面时就销毁。存放临时数据。作用域为page。
exception:作用域为page
形参和实参进行数据传递,形参最好使用接口类型变量来接收。和工厂模式差不多。
父接口的类型变量可以执行子接口引用型变量。
四大作用域:
1、Page:页面范围 只在当前页面中
2、request内置对象分析(Request:请求范围)
后台结果数据叫做属性。
request.setAttribute(“name”,”张三”);//设置属性 属性名是字符串,属性值是任何类型
request.getAttribute(“name”);//拿到属性值,属性值为Object类型
request包含数据区和代码区
参数区:存放请求中的参数(表单中的数据getParameter(“”))String类型
属性区:存放后台设定的属性(setAttribute(“”,””);)Object类型
如果是服务端跳转,request可以传递数据。
每发一次请求,tomcat都会为这个请求创建一个新的request内置对象。
request的生命周期取决于服务端
3、session内置对象分析(Session:用户范围)
session用来存储验证信息,不管什么跳转都可以取得属性。
session.setAttribute(“key”,”value”);//往session中设定验证信息
session.getAttribute(“key”);//从session中取得验证信息
session的生命周期取决于客户端
4、application内置对象分析(Application:服务器范围)
一个application可以给多个项目服务
一个application可以给一个项目中的多个用户服务
application.setAttribute(“key”,”value”);//往application中设定信息
application.getAttribute(“key”);//从application中取得信息
缺点:不安全,占内存
application的生命周期取决于服务端
PageContext(不推荐使用)
pageContext.setAttribute(“key”,”value”,PageContext.APPLICATION_SCOPE);//将数据设置到application中
pageContext.setAttribute(“key”,”value”,PageContext.REQUEST_SCOPE);//将数据设置到request中
pageContext.setAttribute(“key”,”value”,PageContext.PAGE_SCOPE);//将数据设置到page中
pageContext.setAttribute(“key”,”value”,PageContext.SESSION_SCOPE);//将数据设置到session中
表单参数的收集:
复选框:<input type=”checkbox” name=”interest” value=”sing” >唱歌</input>
<input type=”checkbox” name=”interest” value=”dance”>尬舞</input>
一个参数名对应多个参数值,用字符串数组对象接收
String[] inst=request.getParameteValues(“interest”);//新字符串的长度,取决于值的个数
type=”text”:参数名为name,不输入数据时 ,显示参数值为 空串。
type=”checkbox”:参数名为interest,不输入数据是 ,显示的参数值为null。
如果复选框interest中没有选中任何值,那么inst数组对象为null,会产生空指针异常。
解决办法:
<%@page contentType="text/html;charset=UTF-8"%>//设置静态编码
<%@page import="java.util.*"%>//导入util包
request.setCharacterEncoding("UTF-8");//设置jsp动态代码的编码
把request中的所有参数都放入Enumatioin集合中
Enumeration enu=request.getParameterNames();//enu只收集有确切参数值的参数名,所以后面不会发生空指针异常 ,会收集空串,但是不收集null.先收集后迭代。
while(enu.hasMoreElements()){
String name=(String) enu.nextElement();
String[] values=request.getParameterValues(name);
for(int i=0;i<values.length;i++){
out.println(values[i]+”**==**”);
}
}
优点:健壮性好,拥抱需求
request.getRemoteAddr();//得到用户的MAC地址,IP地址:127.0.0.1
作业一: 解析Enumeration迭代取出表单中的参数名和参数值
在未知表单中的参数个数,一个参数对应的参数值的个数的情况下,使用Enumeration接口变量接收request域中有确切参数的参数名。
Enumeration enu=request.getParameterNames();//只收集有确切参数值的参数名,所以后面不会发生空指针异常 ,会收集空串,但是不收集null。先收集后迭代。
while(enu.hasMoreElements()){//判断集合中是否有元素
String name=(String) enu.nextElement();//取出表单中具有参数值的参数名
String[] values=request.getParameterValues(name);//用数组对象接收参数名对应的参数值,数组的长度取决于参数名对应参数值的个数。
for(int i=0;i<values.length;i++){//遍历输出当前参数名对应的所有参数值
out.println(values[i]+”**==**”);}}//将参数值发送到浏览器显示
request内置对象
从客户端拿数据:
request.getParameter();
request.getParameterValues();
request.getParameterNames();
动态编码:
1、String name=request.getParameter(“name”);//得到请求中的参数值
byte[] b=name.getBytes(“utf-8”);//把未经编码的汉字变成字节数组对象,然后对字节数组对象编码
name=new String(b);//把编码后的字节数组对象转换成字符串
编码优点:post请求和get请求都可以编码,编码成功率高。
编码缺点:代码量大,可行不可用,服务端跳转后从同一个request中拿数据也不用再编码
2、request.setCharacterEncoding(“UTF-8”);
对request中所有汉字做编码
编码优点:代码量小
编码缺点:只支持post请求,不支持get请求(只能对协议体中的汉字做编码,对协议体中的汉字不做编码),编码成功率不是很高
response:内置对象
接口:HttpServletResponse
采用http协议
主要作用:工作在jsp页面中,自动和客户端建立信道,把结果数据和静态代码通过信道发给浏览显示。
通过修改协议头,控制浏览器自动发请求
1、 定时刷新:response.setHeader(“refresh”,”1”);//往http协议头中设定控制信息
2、 定时跳转:response.setHeader(“refresh”,”1;URL=1.jsp”);
定时跳转,完成跳转的是浏览器;
定时刷新,完成刷新的是浏览器
3、 定时跳转:response.sendRedirect(“1.jsp”);//重定向,客户端跳转,服务器在协议头中设定控制信息,不会完成跳转,后面的代码依旧会执行。
服务端跳转:
<jsp:forward page=”1.jsp”/>//只能在jsp页面中使用
request.getRequestDispatcher(“1.jsp”).forward(request,response);//既可以完成页面之间的跳转,也可以完成页面和组件之间的跳转和组件与组件之间的跳转
服务端跳转不可重新传递参数,跳转代码后面代码不会被执行。
结论:正常流程使用服务端跳转,异常流程(出错流程)使用客户端跳转
服务端跳转和客户端跳转
相同点:都是完成跳转
不同点:
①语法不同。客户端 response.sendredirect(..)
服务端Request.getrequestDispatcher(…).forward(request,response)
②跳转实质不同
客户端跳转:服务器向http头设置控制信息,真正完成跳转的是浏览器
服务器跳转:服务器完成跳转
③客户端跳转:浏览器要重新发请求 ,地址栏会发生变化
服务器跳转:不会重新发请求 地址栏不会发生变化
④客户端跳转:不能跨组件传递信息,因为重新发请求!第一个请求里的信息已经丢失,可以重新传参
服务器跳转:可以跨组件传递信息,不能重新传参
结论:正常流程用服务端跳转
异常流程用客户端跳转,给客户做一个提示!
超链接和表单:
共同点:
都属于前台技术,由浏览器执行
都能自动生成http协议,不用手动写
都可以传递参数
不同点:
超链接不能和用户做交互,表单可以和用户做交互
超链接不能产生post请求,不能把参数放入协议体中;表单可以
超链接不安全,不能使用动态编码
使用特点:
表单:和用户交互,安全性高的时候用表单
超链接:不能和用户交互,只是执行功能时使用,超链接简单
状态码:
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更