Servlet
Servlet配置
<!-- 配置一个servlet -->
<!-- servlet的配置 -->
<servlet>
<!-- servlet的内部名称,自定义。尽量有意义 -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的类全名: 包名+简单类名 -->
<servlet-class>gz.itcast.a_servlet.FirstServlet</servlet-class>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
<!-- servlet的内部名称,一定要和上面的内部名称保持一致!! -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的映射路径(访问servlet的名称) -->
<url-pattern>/first</url-pattern>
</servlet-mapping>
Servlet的映射路径
1)url-pattern要么以 / 开头,要么以*开头。 例如, itcast是非法路径。
2)不能同时使用两种模糊匹配,例如 /itcast/*.do是非法路径
3)当有输入的URL有多个servlet同时被匹配的情况下:
3.1 精确匹配优先。(长的最像优先被匹配)
3.2 以后缀名结尾的模糊url-pattern优先级最低!!!
url-pattern 浏览器输入
精确匹配 /first http://localhost:8080/day10/first
/itcast/demo1 http://localhost:8080/day10/itcast/demo1
模糊匹配 /* http://localhost:8080/day10/任意路径
/itcast/* http://localhost:8080/day10/itcast/任意路径
*.后缀名 http://localhost:8080/day10/任意路径.do
*.do
*.action
*.html(伪静态)
生命周期方法
- 构造方法
- init方法
- service方法
- destroy方法
生命周期过程
浏览器客户端向服务器端发送请求
http://localhost:8080/ReqeustDemo/HelloServlet
Tomcat服务器解析地址,获取资源名称/RequestDemo,进入该Web目录下,查找web.xml,是否有/HelloServlet的url-pattern,如果有该url-pattern则查找Servlet-name然后再Servlet-class
通过反射创建该Servlet对象,Servlet的构造方法被调用
创建ServletConfig对象,通过反射调用init方法
创建Response和Request对象,通过反射调用Service方法
服务器关闭或者项目重新部署,调用destroy方法
Servlet默认为用户第一次访问时调用,该对象为单例多线程对象。因此会有线程安全问题
解决办法:
1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)
2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。
通过设置load-on-startup可以在tomcat加载该应用时就创建和初始化该Servlet对象
<!-- 让servlet对象自动加载 -->
<load-on-startup>1</load-on-startup> 注意: 整数值越大,创建优先级越低!!
init的无参和有参数方法
无参方法是给程序员写代码用的,有参数方法默认会调用无参方法
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
ServletConfig对象
ServletConfig对象: 主要是用于加载servlet的初始化参数。在一个web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)
创建时机: 在创建完servlet对象之后,在调用init方法之前创建。
得到对象: 直接从有参数的init方法中得到!!!
ServletConfig的API:
java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值
java.util.Enumeration getInitParameterNames() 获取所有参数
ServletContext getServletContext() 得到servlet上下文对象
java.lang.String getServletName() 得到servlet的名称
ServletContext对象
ServletContext对象 ,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一个ServletContext对象。
创建时机:加载web应用时创建ServletContext对象。
得到对象: 从ServletConfig对象的getServletContext方法得到
獲取Web應用的初始化參數
java.lang.String getInitParameter(java.lang.String name) --得到web应用的初始化参数 java.util.Enumeration getInitParameterNames()
獲取域對象
void setAttribute(java.lang.String name, java.lang.Object object) --域对象有关的方法 java.lang.Object getAttribute(java.lang.String name) void removeAttribute(java.lang.String name)
轉發
RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(类似于重定向),等價于request.getRequestDispatcher(java.lang.String path)
獲取Web資源
java.lang.String getRealPath(java.lang.String path) --得到web应用的资源文件 java.io.InputStream getResourceAsStream(java.lang.String path)
得到Web應用的路徑
java.lang.String getContextPath() --得到当前web应用的路径,類似于request的getContextPath()
Web應用中/和.的含義:
目标资源是给谁使用的
- 给服务器使用的: / 表示在当前web应用的根目錄(webRoot下)
- 给浏览器使用的: / 表示在webapps的根目錄下
1. 转发 目標資源是給瀏覽器使用,故/表示的爲webapps目錄
2. 请求重定向 目標資源給服務器使用,故/表示爲當前web應用的根目錄下
3. html页面的超连接href /表示webapps根目錄
4. html页面中的form提交地址 /表示webapps根目錄
ServletContext域对象:作用范围在整个web应用中有效!!!
所有域对象:
HttpServletRequet 域对象
ServletContext域对象
HttpSession 域对象
PageContext域对象
请求转发与重定向
RequestDispatcher getRequestDispatcher(java.lang.String path)
1)转发
a)地址栏不会改变
b)转发只能转发到当前web应用内的资源
c)可以在转发过程中,可以把数据保存到request域对象中
2)重定向
a)地址栏会改变,变成重定向到地址。
b)重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站。
c)不能再重定向的过程,把数据保存到request中。
结论: 如果要使用request域对象进行数据共享,只能用转发技术!!!
Cookie和Session
Cookie原理
在服務器產生Cookie對象,通過設置響應頭(set-cookie)傳遞到瀏覽器;瀏覽器下次訪問的時候會將該cookie添加到請求頭(cookie)傳遞到服務器,服務器可以通過request或得cookie。Cookie是存儲在瀏覽器端的。
創建Cookie對象
Cookie cookie = new Cookie("name","value);
服務器發送Cookie信息到瀏覽器
response.setHeader("set-cookie","name=value");
或
response.addCookie(cookie);
- 瀏覽器得到服務器發送的cookie
- 下次訪問會帶著cookie訪問服務器
服務器接收瀏覽器帶來的cookie
request.getCookies();
Cookie核心API
1)构造Cookie对象
Cookie(java.lang.String name, java.lang.String value)
2)设置cookie
void setPath(java.lang.String uri) :设置cookie的有效访问路径
void setMaxAge(int expiry) : 设置cookie的有效时间
void setValue(java.lang.String newValue) :设置cookie的值
3)发送cookie到浏览器端保存
void response.addCookie(Cookie cookie) : 发送cookie
4)服务器接收cookie
Cookie[] request.getCookies() : 接收cookie
Cookie細節
void setPath(java.lang.String uri) :设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。
void setMaxAge(int expiry) : 设置cookie的有效时间。
正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
零:表示删除同名的cookie数据
Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
Session
Session的会话数据保存在服务器端。(内存中)
Session原理
前提: 在哪个session域对象保存数据,就必须从哪个域对象取出!!!!
浏览器1:(给s1分配一个唯一的标记:s001,把s001发送给浏览器)
1)创建session对象,保存会话数据
HttpSession session = request.getSession(); --保存会话数据 s1
浏览器1 的新窗口(带着s001的标记到服务器查询,s001->s1,返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --可以取出 s1
新的浏览器1:(没有带s001,不能返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --不可以取出 s2
浏览器2:(没有带s001,不能返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --不可以取出 s3
代碼解讀
1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID
new HttpSession();
2)把JSESSIONID作为Cookie的值发送给浏览器保存
Cookie cookie = new Cookie("JSESSIONID", sessionID);
response.addCookie(cookie);
3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器
4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。
if(找到){
return map.get(sessionID);
}
Map<String,HttpSession>]
<"s001", s1>
<"s001,"s2>
5)如果找到对应编号的session对象,直接返回该对象
6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程
结论:通过JSESSION的cookie值在服务器找session对象!!!!!
核心API
java.lang.String getId() : 得到session编号
两个getSession方法:
getSession(true) / getSession() : 创建或得到session对象。没有匹配的session编号,自动创 建新的session对象。
getSession(false): 得到session对象。没有匹配的session编号,返回nullvoid setMaxInactiveInterval(int interval) : 设置session的有效时间
session对象销毁时间:1 默认情况30分服务器自动回收
2 修改session回收时间
3 全局修改session有效时间
<!-修改session全局有效时间:分钟 --> <session-config> <session-timeout>1</session-timeout> </session-config>
4.手动销毁session对象
void invalidate():销毁session对象