首页 > 代码库 > Java WEB 笔记
Java WEB 笔记
1. 部署并启动 tomcat 服务器
1). 解压 apache-tomcat-version 到一个非中文目录下
2). 配置一个环境变量,JAVA_HOME(指向 JDK 安装目录)或 JRE_HOME
3). 通过双击 apache-tomcat-version\bin 目录下的 catalina run 或 startup.bat,启动服务器,catalina.bat
4). 可以在浏览器中输入 localhost:8080 来检验 Tomcat 安装是否正确
5). 若已经启动了一个Tomcat 应用,若再启动同一个 Tomcat 应用,会抛出异常:Address already in use: JVM_BIND:8080,端口已经被占用(如果报错屏幕一闪而过,改用命令:catalina run 启动)
2. Tomcat:开源的 Servelet 容器
3. 修改端口号:server.xml
举例:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
4. 为了可以在任意目录启动 Tomcat 服务器
4.1 把 \PATH\TO\TOMCAT\BIN 添加到 PATH 环境变量
运行 catalina 命令还是报错:
The CATALINA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
即:要求设置 CATALINA_HOME 环境变量
配置环境变量:
catalina_home
G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67
5. 通过阅读startup.bat 批处理文件,可知catalina_home 环境变量下有一个bin目录,而bin目录又有一个catalina.bat文件,由此可知catalina_home 指向的应该是 Tomcat 安装的根目录
于是把Tomcat 的根目录设为 CATALINA_HOME 环境变量
再跑一下,启动成功
6. 继续阅读startup.bat 文件,发现启动tomcat 服务器的是 catalina.bat 命令
可查看该命令的选项帮助
如下:
G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67\bin>catalina --help
Using CATALINA_BASE: "G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67"Using CATALINA_HOME: "G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67"Using CATALINA_TMPDIR: "G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67\temp"Using JRE_HOME: "C:\Program Files\Java\jdk1.7.0_17\"Using CLASSPATH: "G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67\bin\bootstrap.jar;G:\tomcat7.0\apache-tomcat-7.0.67-windows-x64\apache-tomcat-7.0.67\bin\tomcat-juli.jar"Usage: catalina ( commands ... )commands: debug Start Catalina in a debugger debug -security Debug Catalina with a security manager jpda start Start Catalina under JPDA debugger run Start Catalina in the current window run -security Start in the current window with security manager start Start Catalina in a separate window start -security Start in a separate window with security manager stop Stop Catalina configtest Run a basic syntax check on server.xml version What version of tomcat are you running?
7. 第一个WEB-INF应用程序:开发,并部署到Tomcat 服务器运行
1). 在eclipse 新建一个 Java project
2). 在Java 项目下创建 WEB 开发的目录结构,必须是:
-WebContent(可自定义)
-WEB-INF
-classes(编译后的classes 文件必须放在此目录下)
-lib
-web.xml
html 页面
JSP 页面
图片 ...
3). 在src下新建一个Person类
package first;
public class Person {
public void info(){
System.out.println("info ...");
}
}
4). 手工把Person 类对应的class 文件(含包)复制到classes
可以通过修改默认的输出目录达到把编译好的class放到classes目录中
5). 在WebContent 目录下新建一个JSP文件
<%@page import="first.Person"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
Person person = new Person();
person.info();
%>
</body>
</html>
6). 把WebContext 目录复制到Tomcat的 webapps 目录下,并改名为: helloworld
8. Servlet容器响应客户请求的过程
1). Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步
2). 装载并创建该Servlet的一个实例对象:调用该Servlet的构造器
3). 调用Servlet实例对象的init()方法
4). 创建一个用于封装请求的ServletRequest对象和一个代表响应消息的ServeletResponse对象,然后条用Servlet的service()方法并将请求和响应对象作为参数传递进去
5). WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法
9. 使用javaEE版的eclipse开发动态的WEB工程
1). 在servers 面板中新建Tomcat 服务器,一定要关联到Tomcat 安装根目录
2). 新建一个Dynamic Web Project,其中Target Runtime需选择Tomcat6.0
3). 开发java web 应用
4). 可以通过run on server 来运行Web项目
10. Servlet的本质:是通过客户端基于http协议访问Servlet容器中的java类,该java类实现了servelet接口
1). 创建一个Servlet 接口的实现类
2). 在web.xml 文件中配置和映射这个Servlet
<!-- 配置和映射Servlet -->
<servlet>
<!-- Servlet 注册的名字 -->
<servlet-name>hello</servlet-name>
<!-- Servlet 的全类别 -->
<servlet-class>com.webapp.Helloworld</servlet-class>
</servlet>
<servlet-mapping>
<!-- 需要和某一个servlet 节点的servlet-name 子节点的文本节点一致 -->
<servlet-name>hello</servlet-name>
<!-- 映射具体的访问路径:/ 代表当前WEB 应用的根目录 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
11. Servlet 容器:运行Servlet、JSP、Filter 等的软件环境
1). 可以创建Servlet,并调用Servlet 的相关生命周期方法
2). Servlet、JSP、Filter,Tag ...
12. Servlet 生命周期的方法:以下方法都是由|Servlet 容器负责调用
1). 构造器:第一次请求Servlet 时,创建Servlet 的实例,调用构造器
这说明Servlet 是单实例的!很重要
2). init方法:只调用一次,在创建好实例后立即被调用,用于初始化当前Servlet
3). service:被多次调用,每次请求都会调用service 方法,实际用于响应请求的
4). destroy:只被调用一次,在当前Servlet 所在的WEB 应用被卸载前调用,用于释放当前Servlet 所占用的资源
5). 如何实现在当前WEB 应用被加载的时候,就创建Servlet 实例?
参数:load-on-startup,可以指定 Servlet 被创建的时机
负数:在第一次请求时被创建
正数:在当前Servlet 容器加载时创建实例,且数组越小越早被创建
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.webapp.Helloworld2</servlet-class>
<!-- 可以指定 Servlet 被创建的时机 -->
<load-on-startup>1</load-on-startup>
</servlet>
13. ServletConfig
封装了Servlet 的配置信息,并可以获取ServletContext 对象
这是个接口,由Servlet 容器(tomcat)实现
1). 获取servlet 初始化参数
<!-- 局部参数,仅 本servlet 可用 -->
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>admin123</param-value>
</init-param>
注意:必须放在 load-on-startup 之前
2). 获取初始化参数:
> getInitParameter(string name):获取指定参数名的初始化参数值
> getInitParameterNames():获取参数名组成的Enumeration 对象
String username = arg0.getInitParameter("username");
String password = arg0.getInitParameter("password");
System.out.println("username: "+username);
System.out.println("password: "+password);
3). 获取Servlet 的配置名称
String serlvetName = arg0.getServletName();
System.out.println("serlvetName: "+serlvetName);
14. ServletContext
由于一个WEB 应用程序中的所有Servlet都共享一个ServletContext 对象。所以,ServletContext 对象被称之为application 对象(WEB 应用程序对象)
1). 设置初始化参数:
<!-- ServletContext全局参数,所有servlet 可用 -->
<context-param>
<param-name>driver</param-name>
<param-value>oralce.jdbc.driver</param-value>
</context-param>
2). 获取参数:
ServletContext servletContext = arg0.getServletContext();
String driver = servletContext.getInitParameter("driver");
3). 获取当前WEB 应用的名称
String contextPath = arg0.getServletContext().getContextPath();
System.out.println("contextPath: "+contextPath);
15. HTTP 协议
1). WEB 浏览器与WEB 服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议
2). HTTP 是hypertext transfer protocal(超文本传输协议的简写),它是TCP/IP 协议集中的一个应用层协议,【用于定义WEB 浏览器与WEB 服务器之间交换数据的过程以及数据本身的格式】
3). HTTP 请求消息的结构
一个请求行,若干消息头,以及实体内容,其中的一些消息头和实体内容是可选的,消息头和实体内容之间要用空行隔开。
举例:
GET /book/java.html HTTP/1.1 --> 请求行
Accept "/" --> 多个消息头
Accept-language: en-us --> 多个消息头
Connection: Keep-alive --> 多个消息头
Host: localhost --> 多个消息头
Referer: http://localhost/links.asp --> 多个消息头
User-Agent: Mozilla/4.0 --> 多个消息头
Accept-Encoding: gzip,deflate --> 多个消息头
--> 一个空行
<HTML><BODY> ... </BODY></HTML> --> 实体内容
注意:
只有post方法的请求信息才会有实体内容
4). HTTP 响应消息的结构
一个状态行,若干消息头,以及实体内容,其中的一些消息头和实体内容是可选的,消息头和实体内容之间要用空行隔开。
举例:
HTTP/1.1 200 OK --> 状态行
Server:Microsoft-IIS/5.0 --> 多个消息头
Date: Thu 13 Jul 2000 05:46:53 GMT --> 多个消息头
Content-length: 2291 --> 多个消息头
Content-type: text/html --> 多个消息头
Cache-control: private --> 多个消息头
--> 一个空行
<HTML><BODY> ... </BODY></HTML> --> 实体内容
5). 请求方式: get
特点:传递的参数数量是有限制的,一般限制在1KB以下
举例:
GET /servlet/reg?param1=abc&parma2=def HTTP/1.1
6). 请求方式: post
特点:传送的数据量要比GET 方式大得多
举例:
POST /servlet/reg HTTP/1/1
HOST
Content-type:application/x-www-form-urlencoded
Context-length:280
> String getParameter(string name): 根据请求参数的名字,返回参数值
若请求参数有多个值(例如checkbox),该方法只能获取第一个提交的值
> String[] getParameterValues(string name);
根据请求参数的名字,返回请求参数对应的字符串数组
16. ServletRequest 和 ServletResponse
这两个接口都是 Servlet 容器实现的。tomcat、webshere等各有自己的实现。
ServletRequest:封装了请求信息,可以从中获取任何的请求信息
ServletResponse:封装了响应信息,如果想给用户什么响应,具体可以使用该接口的方法实现
17. ServletRequest
HttpServletRequest:是ServletRequest 的子接口,针对于 HTTP 请求所定义,里边包含了大量获取HTTP请求相关的方法
获取请求Servlet 的映射路径
String servletPath = httpServletRequest.getServletPath();
System.out.println(servletPath);
18. ServletResponse
1). 返回PrintWriter 对象,调用该对象的print、writer方法,将把print()中的参数直接打印到客户的浏览器中
PrintWriter printWriter = resp.getWriter();
printWriter.write("IT WORK");
2). 设置响应的内容类型
resp.setContentType("application/msword");
F:\work2014\Tomcat6.0\conf\web.xml 中定义有响应类型:
<!-- ===================== Default MIME Type Mappings =================== -->
<!-- When serving static resources, Tomcat will automatically generate -->
<!-- a "Content-Type" header based on the resource‘s filename extension, -->
<!-- based on these mappings. Additional mappings can be added here (to -->
<!-- apply to all web applications), or in your own application‘s web.xml -->
<!-- deployment descriptor. -->
3). 请求的重定向
HttpServletResponse 是ServletResponse 的子接口,针对于HTTP 响应所定义,里边包含了大量获取HTTP返回相关的方法
19. GenericServlet
1). 是一个servlet,是Servlet接口和ServletConfig接口的实现类,它是一个抽象类
2). 如果新建的Servlet 程序直接继承GenericServlet会使开发更简洁
3). 在GenericServlet 中申明了一个ServletConfig 类型的成员变量,在init(ServletConfig)方法中对其进行了初始化
4). 还定义了一个init()方法,在init(ServletConfig)方法中对其进行进行调用,子类可以直接覆盖init()在其中实现对Servlet的初始化
注意:
不建议直接覆盖init(ServletConfig),因为如果忘记编写super.init(servletConfig),而还是使用了ServletConfig 接口的方法,会抛出空指针异常
5). 新建的init(){} 并非Servlet 的生命周期方法,而init(servletConfig)是生命周期相关的方法
20. httpServlet
1). 是一个Servlet,继承自GenericServlet,针对 HTTP 协议所定制
2). 在service()方法中直接把ServletRequest 和 ServetResponse 转为 HttpServletRequest 和HttpServletResponse 并调用了重载的service(HttpServletRequest,和HttpServletResponse)
21. JSP的运行原理:JSP 本质上是一个Servlet
每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet 程序,然后再把这个 Servlet 源程序编译成Servlet 的class 类文件。然后再由WEB 容器(Servlet容器)像调用 Servlet 程序一样的方式装载和解释执行这个由JSP 页面翻译成的 Servlet 程序。
JSP引擎:
负责将JSP 编译成Servlet程序,由Servlet容器提供。比如Tomcat 提供的:org.apache.jasper.servlet.JspServlet
所以,JSP被编译成Servlet程序最本质原理是,Tomcat全局实例中(Tomcat6.0\conf\web.xml)中配置了JspServlet编译器,凡是以*.jsp和*.jspx结尾的请求,Tomcat 都会调用 org.apache.jasper.servlet.JspServlet 进行处理
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<!-- The mapping for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
注意: JSP 可以放置在 WEB 应用程序中的除了 WEB-INF 及其子目录外的其它任何目录中,JSP页面的访问路径和普通HTML 页面的访问页面的访问路径完全一样
22. JSP页面的9个隐藏对象
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
使用<% %> 编写代码的位置,可以用到request,response,pageContext,session,application,config,out,page 这8个隐藏对象(实际上还可以使用一个叫exception 的隐藏对象)
1). request: HttpServletRequest 的一个对象
2). response: HttpServletResponse 的一个对象(在JSP 页面中几乎不会调用 response 的任何方法)
3). pageContext:页面的上下文,是PageContext 的一个对象,可以从该对象中获取到其他 8 个隐藏对象,也可以从中获取到当前页面的其它信息。(学习自定义标签时使用它)
4). session:代表浏览器与服务器的一次会话,是HttpSession 的一个对象,后面详细学习。
5). application: 代表当前WEB 应用,是ServletContext 对象,可以获取当前应用的配置信息
6). config: 当前JSP对应的Servlet 的ServletCofig 对象(开发时几乎不用),若需要访问当前JSP配置的初始化参数,需要通过映射的地址才可以
举例:
<servlet>
<servlet-name>hellojsp</servlet-name>
<jsp-file>/hello.jsp</jsp-file>
<!-- 局部参数,仅 本servlet 可用 -->
<init-param>
<param-name>username</param-name>
<param-value>jackson</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hellojsp</servlet-name>
<url-pattern>/hellojsp</url-pattern>
</servlet-mapping>
7). out:jspWriter,经常调用out.println()方法,可以直接把字符串内容打印到浏览器上
8). page:指向当前JSP 对应的 Servlet 对象的引用,但是Object 类型,(开发几乎不用)
9). exception:在申明了 page 指令的isErrorPage="true" ,才可以使用
23. 查看JSP经过JSP引擎编译后的文件
项目Location:F:\work2014\eclipse2\Workspace\webHelloworld
启动项目后*.jsp文件位置:TOMCAT的\work目录下
a. eclipse中使用Tomcat作为Server默认部署位置在项目工作空间的.metadata目录下
比如:F:\work2014\eclipse2\Workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\work\Catalina\localhost\webHelloworld\org\apache\jsp
b. 可以右击Servers下的Tomcat选择open,打开Server Overview,修改Server locations下的Server path和Deploy path
注意:只有在项目启动,跑起来后TOMCAT才会在Tomcat6.0\work\Catalina\localhost\webHelloworld\org\apache\jsp 路径下把*.jsp文件编译成*—jsp.java文件
24. 请求的转发和重定向
1). 本质区别
请求的转发只发出了一次请求,而重定向则发出了两次请求
转发:
地址栏是初次发出请求的地址
在最终的Servlet 中,request 对象和中转的那个 request 是同一个对象
重定向:
地址栏不再是初次发出请求的地址,地址栏为最后响应的地址
在最终的Servlet 中,request 对象和中转的那个 request 不是同一个对象
25. WEB_page指令,page指令常用属性:
1). import 属性:指定当前JSP 页面对应的Servlet 需要导入的类
如:<% page import="java.text.DateFormat" %>
2). session属性:取值为true 或 false;默认为true,指定当前页面的session 隐藏变量是否可用,也可以说访问当前页面时是否一定要生成HttpSession对象
3). errorPage 和 isErrorPage
> errorPage 指定若当前页面出现错误的实际响应页面是什么。其中/ 表示的是当前WEB 应用的根目录
<%@ page errorPage="/error.jsp" %>
> 在响应error.jsp 时,JSP引擎使用的是请求转发的方式
> isErrorPage 指定当前页面是否为错误处理页面,可以说明当前页面是否可以使用exception 的隐藏变量。需要注意的是:若指定isErrorPage=“true”,并使用 exception 的方法了,一般不建议能够直接访问该页面
> 如何是客户不能直接访问某一个页面呢?对于Tomcat 服务器而言,WEB-INF 下的文件是不能通过在浏览器中直接输入地址的方式来访问的,但通过请求的转发是可以的。
> 还可以在 web.xml 文件中配置错误页面
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/error_500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/error_404.jsp</location>
</error-page>
4). contentType:指定当前JSP 页面的响应类型,实际调用的是response.setContentType("text/html;charset=UTF-8");通常情况下,对于JSP 页面而言其取值均为text/html;charset=UTF-8,charset 指定返回的页面的字符编码是什么,通常取值为 UTF-8
5). pageEncoding:指定当前JSP 页面的字符编码,通常请看下该值和contentType 中的charset 一致。
6). isElIgnored 指定当前 JSP 页面是否可以使用 EL 表达式。默认是 false
26. include 指令
用于通知JSP 引擎在翻译当前JSP 页面时将其他文件中的内容合并进当前 JSP 页面转换成的Servlet 源文件中,这种在源文件级别进行引入的方式被称之为静态引入,当前JSP 页面与静态引入的页面紧密结合为一个Servlet
语法:
<%@ include file="relativeURL" %>
其中的file 属性用于指定被引入文件的相对路径
细节
> 在将JSP 文件翻译成Servlet 源文件时,JSP 引擎将合并被引入的文件与当前JSP 页面中的指令元素(设置pageEncoding 属性的page 指令除外),所以,除了import 和 pageEncoding 属性之外,page 指令的其它属性不能在这两个页面中有不同的设置值。
> file 属性的设置值必须使用相对路径
> 如果以“/” 开头,表示相对于当前WEB 应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。
27. jsp:include 标签
1). <jsp:include page="b.jsp"></jsp:include>
2). 动态引入:并不是像include 指令生成一个Servlet 源文件,而是生成两个 Servlet 源文件
28. include指令和 jsp:include 标签本质区别
include指令
a. 生成一个Servlet,在一个Servlet中处理
b. 可以向引入的文件传参
jsp:include 标签
a. 生成两个Servlet,在两个Servlet中处理
b. 不可以直接向引入的文件传参
c. 传参可以通过子标签 jsp:param
29. jsp:forward
1). <jsp:forward page="/include/b.jsp"></jsp:forward>
相当于
<%
request.getRequestDispatcher("/include/b.jsp").forward(request,response);
%>
2). 但使用jsp:forward 可以使用 jsp:param 子标签向 b.jsp 传入一些参数,同样 jsp:include也可以,
在b.jsp中使用 request.getParameter("username") 即可取到
29.1. C标签
30. JSP乱码
1). 在JSP 页面上输入中文,请求页面后不出现乱码:
a. 保证这两行编码一致
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page pageEncoding="UTF-8"%>
比如这样写就会乱码:
<%@ page language="java" contentType="text/html; charset=iso8859-1" %>
<%@ page pageEncoding="utf-8"%>
b. 保证浏览器的显示的字符编码也和请求的JSP 页面的编码一致
2). 获取中文参数值乱码: 默认参数在传输过程中使用的编码为 ISO-8859-1
a. 对于POST 请求:只要在调用request.getParameter或者 request.getReader 前加上 request.setCharacterEncoding("UTF-8");就不会乱码
b. 对于 GET 请求:前面的方式无效。
方法一:
String username = request.getParameter("username");
username = new String(username.getBytes("iso-8859-1"),"utf-8");
方法二:
需要在WEB服务器的Connector节点中配置:useBodyEncodingForURI="true"
具体,请间tomcat 官方文档,http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
比如:
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" useBodyEncodingForURI="true"/>
31. 在Servlet 规范中,常用以下两种机制完成会话跟踪:
Cookie
Session
32. Cookie
随便聊聊:问题是什么?有哪些技术?如何解决
背景:
HTTP 协议是一种无状态的协议,而需求是 WEB 服务器必须采取一种机制,能唯一的识别某个用户
WEB应用的会话:
一个客户端浏览器与 WEB 服务器之间连续发生的一系列请求和响应过程
WEB应用的会话状态:
WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB 服务器能够把属于统一会话中的一系列的请求和响应过程关联起来。
如何实现有状态的会话:
WEB 服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,即能识别出来自同一个浏览器的访问请求;
这需要浏览器对其发出的每个请求信息都进行标识:
属于同一个会话中的请求信息都附带同样的标识号,否则总是附带不同的标识号,这个标识号就称之为会话ID(SessionID)
1). cookie是完成会话跟踪的一种机制,采用的是在客户端保持HTTP状态信息的方案
2). Cookie 是在浏览器访问WEB 服务器的某个资源时,由 WEB 服务器在 HTTP 响应消息头中附带传送给浏览器的一个小文本文件
3). 一旦 WEB 浏览器保存了某个 Cookie,那么它在以后每次访问该 WEB 服务器时,都会在 HTTP 请求头中将这个 Cookie 回传给 WEB 服务器
4). 底层的实现原理: WEB 服务器通过在 HTTP 响应消息中增加 Set-Cookie 响应头字段将 Cookie 信息发送给浏览器,浏览器则通过在 HTTP 请求消息中增加Cookie请求头字段将Cookie回传给 WEB 服务器
5). 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和值(VALUE)
6). 一个WEB 站点可以给一个WEB 浏览器发送多个Cookie,一个WEB浏览器也可以存储多个 WEB 站点提供的 Cookie。
7). 浏览器一般只运行存放300个 Cookie,每个站点最多存放 20 个Cookie,每个Cookie 的大小限制为4k
8). 会话 Cookie 和持久化 Cookie 的区别
a. 如果不设置过期时间,则表示这个Cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话Cookie,会话Cookie一般不保存在硬盘上而是保存在浏览器的内存里
b. 如果设置了过期时间,浏览器就会把 Cookie 保存到硬盘上,关闭后再次打开浏览器,这些 Cookie 依然有效直到超过设定的过期时间
// 设置 Cookie 的最大时效,以秒为单位,0表示删除该 cookie
cookie1.setMaxAge(30); // maxAge 服务端获取不到,永远都是 -1
// 可以通过setPath设置Cookie的作用范围,/表示站点的根目录,实现自动登录时必须加上,以避免读取不到
cookie.setPath("/");
cookie1.setPath(request.getContextPath());// 作用于全局,去掉之后cookieRead.jsp将读取不到
response.addCookie(cookie1);
9). 两个应用
9.1). 自动登录
9.2). 小时浏览过的商品的信息
33. HttpSession
1). HttpSession:
在服务器端保持HTTP状态信息的方案;与其对应的是Cookie
2). 产生HttpSession的过程:
当程序需要为某个客户端的请求创建一个 session 时,服务器:
2.1). 首先检查这个客户端的请求里是否包含了一个 session 标识(即:JSESSIONID),
如果已经包含一个 JSESSIONID,则说明以前已经为此客户创建过sesion,服务器就按照这个 JSESSIONID 把这个sesion检索出来使用;如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的sesion对象,但用户人为的请求的URL后面附加上一个JSESSIONID的参数;
2.2). 如果不包含一个 JSESSIONID,则为此客户创建一个 session,并且生成一个与此 session 相关联的 sessionId(JSESSIONID),这个 JSESSIONID 将在本次响应中返回给客户端。
3). 使用 Cookie 来跟踪 Session:session 通过JSESSIONID来区分不同的客户,session是以cookie或url重写为基础的,默认使用cookie来实现,系统能够会创建一个名为 JSESSIONID 的输出Cookie,这称为session cookie,session cookie存储于浏览器内存中,并不是写到磁盘上的,通常看不到JSESSIONID。
4). HttpSession 的生命周期
4.1). 什么时候初始化?
一个常见的错误是认为,客户端访问的时候就创建。(第一次访问的资源是JSP页面,且page指令的session属性为false时,不会创建session)
a. servlet端程序调用 HttpServletRequest.getSession(true)或者HttpServletRequest.getSession()这样的语句时才会创建;
getSession(boolean create) :
Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session.
b. 第一次访问的资源是JSP页面,且page指令的session属性为 true 时,会创建session
注意:PAGE 指令的 session="false" 到底什么意思?
答:当前隐藏变量禁用 session ,但可以使用显示的 HttpSession 对象
4.2). 什么时候销毁?
a. 程序调用 HttpSession.invalidate()
b. 距离上一次收到客户端发生的 sessionId 时间间隔超过了 session 的最大有效时间
在 web.xml 中定义
<session-config>
<session-timeout>30</session-timeout>
</session-config>
c. session 失效时间,配置说明
30分钟内客户端无操作,服务端自动使 session 失效
c. 服务器进程被停止(或当前 WEB 应用被卸载)
注意:关闭浏览器智慧使存储在客户端浏览器内存中的 session cookie 失效,不会使服务器端的 session 对象失效
5). HttpSession相关的 API
a. 获取 session 对象:request.getSesssion()、request.getSession(boolean create)
b. 属性相关的:setAttribute,getAttribute,removeAttribute
c. 使 HttpSession 失效:invalidate()方法
d. 设置其最大失效的时间间隔:setMaxInactiveInterval()
6). URL重写
a. Servlet 规范中引入了一种补充的会话管理机制,它允许不支持Cookie的浏览器也可以与 WEB 服务器保持连续的会话
b. 将会话标识号以参数形式附加在超链接的 URL 地址后面的技术称为 URL 重写
34. 相对路径和绝对路径
1). 开发时建议使用绝对路径,写绝对路径肯定没有问题,写相对路径可能会有问题。
在由 servlet 转发到 JSP 页面时,此时浏览器地址栏上显示的是 servlet 的路径,而若 JSP 页面的超链接还是相对于该 JSP 页面的地址,就可能出现路径混乱的问题
/a.jsp
-path
b.jsp
c.jsp
a.jsp --> /servlet --> 转发 --> b.jsp (有一超链接:和 b.jsp 在同一路径下的 c.jsp) --> 无法得到页面
2). 改用绝对路径可以避免该问题
3). 什么是绝对路径?
相对于当前 WEB 应用的根路径的路径为绝对路径,也就是下面的 a
yes: http://localhost:8080/contextPath(当前 WEB 应用的上下文路径)/a.jsp
no : http://localhost:8080/a.jsp
4)、如何编写:若 / 代表的是站点的根目录,在其前面加上 contextPath 就可以了
比如:
<a href="http://www.mamicode.com/TestServlet">To B Page</a> --> <a href="http://www.mamicode.com//TestServlet">To B Page</a>
5)、JavaWEB 开发中的 / 到底代表什么?
a. 当前 WEB 应用的跟路径:http://localhost:8080/contextPath/ :若 / 需交由 Servlet 容器来处理时
> 请求转发时:request.getRequestDispatcher("/path/b.jsp").forward(request,response);
> web.xml 文件中映射 Servlet 访问路径:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.webapp.Helloworld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
b. web 站点的根路径:http://localhost:8080/ :若 / 交由浏览器来处理
> 超链接:
> 表单中的 action:<form action="/login.jsp" />
> 做请求重定向的时候:response.sendRedirect("/a.jsp")
35. 表单重复提交
1). 重复提交的情况
a. 在表单提交到一个 servlet,右通过请求转发的方式响应一个 JSP/HTML页面,此时地址栏还保留着 servlet 的那个路径,在响应页面点击刷新
b. 在响应页面没有到达时,重复点击“提交”按钮
c. 点击“返回”,再点击“提交”
2). 不是重复提交的情况
点击“返回”,刷新页面,再点击“提交”
3). 如何避免重复提交
在session 里面放一个token,置入form表单中,提交后,比对session 和 request中的token是否一样,一样就不是重复提交,否则为重复提交。
36. Filter
1). Filter是什么
a. JavaWEB 的一个重要组件,可以对发送到 Servlet 的请求进行拦截,并对响应也进行拦截
b. Filter 是实现了 Filter 接口的 Java 类
c. Filter 需要在 web.xml 文件中进行配置和映射
2). 如何创建一个 Filter,并把他跑起来
a. 创建一个 Filter类:实现 Filter 接口
b. z web.xml文件中配置并映射该Filter
3). Filter被执行顺序和<filter-mapping>在web.xml中的配置顺序有关,和初始化顺序无关,靠前的先被调用
4). <dispatcher>元素:指定过滤器所拦截的资源被 Servlet 容器调用的方式
可以是 REQUEST,INCLUDE,FORWARD,ERROR 之一,默认是 REQUEST
可以设置多个<dispatcher>元素用来指定Filter 对资源的多种调用方式进行拦截
a. REQUEST:当用户直接访问页面时,Web 容器将会调用过滤器。如果目标资源是通过 RequestDispatcher的include{}或forward()方法访问时,那么该过滤器就不会被调用
通过get 或 post直接访问的
b. INCLUDE:如果目标资源是通过 RequestDispatcher的include{} 方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
c. FORWARD:如果目标资源是通过 RequestDispatcher的forward{} 方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
通过<jsp:forward page="" /> 或通过 page 指令的errorPage 转发页面 <%@ page errorPage="/WEB-INF/error.jsp"%>
d. ERROR:如果目标资源是通过 声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
web.xml里定义的方式
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/error_500.jsp</location>
</error-page>
37. Listner
概念:Servlet 监听器: Servlet规范中定义的一种特殊类,它用于监听 web 应用程序中的 ServletContext、HttpSession 和 ServletRequest 域对象的创建与销毁事件,以及检讨这些域对象中的属性发生修改的事件。
1). ServletContextListener
用于监听 servletContext 对象的创建和销毁事件,
典型应用场景:
> 当前 web 应用被加载时创建数据库连接池;
> 创建 Spring 的 IOC 容器;
> 读取当前 web 应用的初始化参数
2). HttpSessionListener
用于监听 HttpSessionListener 对象的创建和销毁事件,监听有多少用户
> 创建:
当第一次访问 WEB 应用中的一个 jsp 或 Servlet 时,且该 JSP 或 Servlet 中还需要创建 session 对象。此时服务器会创建一个 session 对象
> 销毁:
a. session 过期
b. session.invalidate() 主动销毁,退出时注销
c. 当前应用被卸载时
注意:关闭浏览器,并不意味着 session 被销毁,还可以通过 jsessionid 找到服务器中的 session
浏览器:
JSESSIONID=E82F27BE94BEDDBEE3713E0D48FAFE47
浏览器重写:
http://localhost:8080/tgWebFilterAuthority/user/login.jsp;jsessionid=E82F27BE94BEDDBEE3713E0D48FAFE47
3). ServletRequestListener
用于监听 ServletRequestListener 对象的创建和销毁事件,监听有多少请求
不需要在 web.xml 中注册的监听器:
4). HtpSessionBindingListener
监听实现了该接口的 Java 类的对象被绑定到 session 或从 session 中解除绑定的事件
// 当前对象被绑定到 session 时调用该方法
@Override
public void valueBound(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
// 当前对象从 session 解绑时调用该方法
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
5). HttpSessionAttributeListener
6). HttpSessionActivationListener
session 对象存储在 tomcat 服务器的 work\Catalina\localhost\contextPath 目录下。 SESSION.SER
38. 文件上传
39. 文件下载
a. 设置 contentType 响应头:设置响应的类型是什么?通知浏览器是个下载的文件
response.setContentType("application/x-msdownload") ;
b. 设置 Content-Disposition 响应头:通知浏览器不再由浏览器来自行处理(或打开)要下载的文件,而由用户手工完成
response.setHeader("Content-Disposition","attachment;filename=abc.txt");
c. 具体的文件:可以调用 response.getOutputStream() 的方式,以IO流的方式发送给客户。
40. 修改源代码
1). 原则:能不修改不修改
2). 修改源代码,替换jar 包中对应的class 文件
3). 在本地新建相同的包,和类,在这个类中修改即可
41. 国际化(i18n)
1). 什么是国际化和本地化
> 本地化:一个软件在某个国家或地区使用时,采用该国家或地区的语言、数字、货币、日期等习惯。
> 国际化:软件开发时,让它能支持多个国家和地区的本地化应用。使得应用软件能够适应多个地区的语言和文化习俗习惯
> 本地敏感数据:随用户区域信息而变化的数据称为本地信息敏感数据。例如数字,货币、日期、时间等数据
2). 相关的 API
> DateFormat & SimpleDateFormat
> NumberFormat
> MessageFormat
> ResourceBundle
3). 国语国际化资源文件
> properties 文件格式
> 必须提供 基名.properties 文件和 基本_语言代码_国家代码.properties 文件
> 相同的 基名 的资源文件必须有相同的 key
> 可能需要使用 native2ascii 工具把非 asc 码转为 asc 码
4). WEB 的国际化
> 可以使用 request.getLocale() 获取 Locale 对象
> 可以使用 JSTL 的 fmt 标签完成国际化,后面使用框架提供的标签完成
> 实现“中文”和“英文”的切换:
* 提供两个超链接、携带不同的变量值
* 根据变量值确定对应的 Locale 对象
* 把 Locale 对象放入到 sessoion 中
* 绑定 Locale 对应的资源文件
Java WEB 笔记