Java Web高级编程(基础)

---HTTP状态码
400 Bad Request 通常是客户端没有使用正确的请求语法 例如POST或者PUT请求中某个必需字段为空
401 Unauthorized 表示在访问资源或者执行请求的状态转换之前 需要进行认证和授权
403 Forbidden 表示客户端尽管通过了认证 但是还是没有访问资源或者执行请求状态转换的权限
404 Not Found
405 Mehtod Not Allowed 不支持请求的状态转换
406 Not Acceptable 不支持Accept头中的请求的表示格式 例如 客户端请求application/xml 但服务器可能只生成application/json
500 Internal Servlet Error 表示处理请求的过程中发生了异常

GET和HEAD唯一区别 HEAD响应不可以有响应正文 HEAD响应中包含的头必须和GET响应一致 服务器为成功的GET和HEAD返回200 OK响应 并在GET请求的响应正文中包含协商好的数据 GET和HEAD是无用的 他们不应该对服务器的资源产生影响(那删除id为...呢?)

POST请求用于在服务器上创建新的资源 成功 服务器将创建被请求的资源并返回一个201 Created响应 包含一个Location头 指定了新创建的资源的URL POST请求是有用的 非幂等的(创建多个完全相同的POST请求将导致多个资源的创建)

---Servlet是用于接受和响应HTTP请求的Java类 过滤器可以拦截发送给Servlet的请求 通过使用过滤器可以满足各种需求(数据格式化,对返回的数据进行压缩认证和授权)

---Servlet是一个运行在Web服务器中的java小程序, Servlet将会接受和响应来自Web客户端的请求使用HTTP进行通信

---不用Servlet 静态的HTML就是用HTTP协议输出的一堆文本 然后浏览器吧这些文本渲染成html页面 用了Servlet 就是可以动态的生成这个流 所以 你要把HTML标签也在Java程序里面输出 JSP就可以不用手动编写这些HTML的标签的out

---Servlet程序一般继承于HttpServletGenericServlet<---HttpServlet HttpServlet实现了只接受HTTP请求的service方法 然后他提供了响应每种HTTP方法类型的方法的空实现(比如doGet() doPost() doHead() doPut() doDelete()等)

---在web.xml下面 <servlet>标签下加<load-on-startup>1</load-on-startup>
重要:init方法是在Web应用程序启动后 第一个请求到达Servlet的时候调用 要是init方法要完成许多工作 那么Servlet的启动可能会需要很长的时间 加了load-on-startup 就是在Web应用程序启动的时候 Servlet立即启动 (那个数字 越大 启动越晚)

---<servlet>配置的作用是启动Sevlet的 <servlet-mapping>是告诉该Serlvet对哪些请求URL做出响应

---HttpServletRequest 的对象有getInputStream 要是用了 下面这些函数都用不了(还有getReader) HttpServletResponse 的对象有getOutputStream方法 getWriter方法 同上面

---HttpServletRequest


1.获取请求参数
第一次调用请求对象的getParameter, getParameterMap, getParameterNames, getParameterValue  Web容器将判断该请求是否包含了post变量 如果包含了 它将读取请求的InputStream并解析这些post变量 请求的post变量只能读取一次 再次读取的时候会抛异常
简单的说 不要在post方法上用getInputStream和getReader

2.确定与请求内容相关的信息
getContentType()将返回请求的MIME内容类型 例如application/json application/zip text/plain等
getContentLength和getContentLengthLong(内容长度超过2G)都返回了请求正文的长度(以字节为单位)
getCharacterEncoding将返回请求内容的字符编码

3.获取请求的内容
方法getInputStream将返回一个ServletInputStream 方法getReader将返回一个BufferReader 它们都可用于读取请求的内容 (具体的使用是看编码的)

4.获取请求特有的数据 例如URL URI和头
getRequestURL 返回完整的URL 但是不包括查询字符串
getRequestURI 返回URL中的服务器路径部分 例如/application/index.jsp
getServletPath 返回比URI更少的信息 匹配Servlet映射的URL部分 /greeting
getHeader 返回指定名字的头数据 getHeader("contenttype")可以匹配Content-Type头 如果有多个 最好使用getHeaders方法返回所有值的枚举
getHeaderNames 返回请求中所有头数据的名字的枚举(一种遍历所有可用头数据的好方式)

5.会话和Cookie 后面详细说

---HttpServletResponse


1.编写响应正文
2.设置头和其他响应属性

(setHeader setIntHeader setDateHeader 如果现有的响应头已经包含了同名的头 该头数据将会被覆盖 所以可以用addHeader addIntHeader addDateHeader 这些不会覆盖现有的头数据 他们会添加一个额外的值)
setStatus:设置HTTP响应状态码
getStatus:判断当前响应的状态
sendRedirect:将客户端重定向至另一个URL

---Servlet的上下文初始化参数(context-param       getServletContext.getInitParameter()    )
最好写在XML里面
初始化参数(init-param       getServletConfig.getInitParameter()      )
要是用注解来做的话

@Webservlet { initParams = { @WebInitParam ( name = "database", value = "CustomerSupport" ), @WebInitParam ( name = "server", value = "10.0.12.5" ) } }

写在配置(XML)里面的好处就是 改了配置之后,不用重新编译程序 只需要重启应用就可以了

---Web程序是天然的多线程应用程序 Web容器会包含某种类型的线程池 容器收到请求的时候 它将在池中寻找可以用的线程 一旦出现可用线程 浏览器将从线程池中借出线程 并将请求传给线程 由线程处理,此时 该线程对其他请求是不可用的 在普通请求中 线程和请求的关联将会贯穿请求的整个生命周期 只有在请求完成 响应内容已经发送到客户端的时候 该线程才会变成可用状态 并返回到线程池中

---保护共享资源 切记 永远 不要 在静态或者实例变量中存储请求或响应对象 任何属于请求的对象都只应该被用于本地变量和方法参数

---<%@ page contentType="text/html;charset=UTF-8" language="java" %>
相当于 response.setContentType("text/html"); response.setCharacterEncoding("UTF-8") 或者response.setHeader( "Content-Type", "text/htlm; charset = UTF-8" );

---JSP的指令


1.forward指令 可以增加请求参数

jsp-forward.jsp <jsp:forward page="forward-result.jsp">
    <jsp:param name = "age" value = "30"/>
</jsp:forward>

forward-result.jsp // <!-- 使用request内置对象获取age参数的值 -->
<%=request.getParameter("age")%>

用forward的时候 用户请求的地址没有发生改变(还是jsp-forward.jsp) 但是title等等其他的所有,都变成了forward-result.jsp的东西 执行forward的时候 客户端的请求不会丢失 它看着是转发了...其实它没有向新页面发送请求 它只是完全采用了新页面来对用户生成响应

2.include指令 (动态导入) 静态导入是 <%@include file="scriptlet.jsp"%>
动态导入编译成servlet只是使用了一个include方法来插入 静态的是完全融入成一个整体的servlet
静态导入的时候 被导入页面的编译指令(就是页面头上的东西会起作用) 动态导入只是插入body里
的内容 动态导入还可以自己加请求参数

<jsp:include page="forward-result.jsp" >
    <jsp:param name="age" value="32"/>
</jsp:include>

3.与JavaBean相关的指令 useBean setProperty getProperty

// <!-- 创建lee.Person的实例,该实例的实例名为p1 -->
scope是作用域 有page request session application这个你应该懂得 <jsp:useBean id="p1" class="lee.Person" scope="page"/>

// <!-- 设置p1的name属性值 -->
<jsp:setProperty name="p1" property="name" value="crazyit.org"/>

// <!-- 设置p1的age属性值 -->
<jsp:setProperty name="p1" property="age" value="23"/>
重要的是在Person里面 有没有get和set方法 甚至有没有name age都是次要的 // <!-- 输出p1的name属性值 -->
<jsp:getProperty name="p1" property="name"/><br/> 会在jsp页面直接输出的 // <!-- 输出p1的age属性值 -->
<jsp:getProperty name="p1" property="age"/>

使用usebean的时候 除了在页面脚本创建了JavaBean实例之外 还放入了指定的sope

---tomcat是一个web服务器 要实现ServletApi中的大部分接口

为了方便JSP和Servlet等之间交换数据 几乎所有WEB服务器都会提供4个类似Map的结构:application session request page 并允许JSP Servlet吧数据放入(取出) 区别是范围不同
1.application 对整个WEB应用都有效 数据可以被该应用下其他所有的JSP,Servlet访问
2.session 对一次会话 数据被本次会话中的所有jsp servlet共享
3.request 仅对本次请求有效 数据被本次请求中的所有jsp servlet共享
4.page 对当前页面有效
吧数据放入这些 等于扩大了该数据的作用范围
---application
<% 这是放
    application.setAttribute( "counter", String.vlaueOf( ++i ) );
%>
这是取
<%= application.getAttribute( "counter" ); %>

这是在Servlet里面访问

@WebServlet ( name = "get-application", urlPatterns = { "/get-application" } ) public class GetApplication extends HttpServlet { public void service (...) { response.setContentType( "text/html;charset=gb2312" ); PrintWriter out = response.getWriter(); //servlet没有内置对象
        ServletContext sc = getServletConfig().getServletContext(); } }

不过 通常指引吧Web应用的状态数据放入application里面

application还有一个重要作用是获取web.xml里面的context-param 注意 它是context-param
//从配置参数中获取驱动 jsp里面写
String driver = application.getInitParameter("driver");

---需要会话的原因


1.使用会话维持状态
同一客户的不同请求的共享数据 维持状态
HTTP请求自身是完全无状态的 从服务器的角度来说 当用户的Web浏览器打开第一个链接到服务器的套接字时请求就开始了 直到服务器返回最后一个数据包并关闭连接的时候 该请求将结束 此时 在用户的浏览器和服务器之间不再有任何联系 当下一个连接开始的时候 无法将新的请求与之前的请求关联起来
就像购物一样 要是没有维持状态 那你就必须"走进商店,选一个商品,付款离开" 如果你想买另外一个商品的时候 就重复这个过程 要是有维持状态 就是把要买的东西都放入购物车 然后付款离开

2.记住用户
3.启动应用程序工作流

---会话和Cookie

用户浏览器--->第一个请求--->会话中的 Web App Store数据--->需要新的会话--->会话存储
然后 会话存储--->返回会话ID=abc123--->会话中的 Web App Store数据--->响应+会话ID abc123--->用户浏览器

用户浏览器--->第二个请求+会话ID abc123--->会话中的 Web App Store数据--->需要会话abc--->会话存储
然后 会话存储返回会话ID=abc123--->会话中的 Web App Store数据--->响应--->用户浏览器

ID要不可预测 否则容易引起会话劫持

---将会话ID从服务器返回到浏览器中: 会话Cookie(JSESSIONID) 和 URL重写(禁止Cookie)

---会话Cookie
Domain:将告诉浏览器应该将cookie发送到哪个域名中
Path:进一步将cookie限制在相对于域的某个特定URL中,每次浏览器发送请求的时候 他都将找到匹配该域和路径的所有cookie 然后将cookie随着请求一起发送到服务器HttoOnly:

吧cookie限制在直接的浏览器请求中 其他技术 例如js和flash 无法访问cookie

请求1
GET /support HTTP/1.1
Host: www.example.com
响应1
HTTP/1.1 302 Moved Temporarily
Location: https:/www.example.com/support/login
Set-Cookie: JSESSIONID="XXXX"; Domain=.example.com; Path=/; HttpOnly

请求2
GET /support/login HTTP/1.1
Host: www.example.com
Cookie: "XXXX"
响应2
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Lenth: 21765

请求3
GET /support/login HTTP/1.1
Host: www.example.com
Cookie: "XXXX"
响应3
HTTP/1.1 302 Moved Temporarily
Location: https:/www.example.com/support/home
Set-Cookie: remusername=Nick; Expires=Wed, 02-Jun-2021 12:15:47 GMT;
            Domain=.example.com; Path=/; HttpOnly

remusername:实际的功能 记住用户名 用来演示cookie的另一种用法 以及如何在Cookie请求头中传输多个cookie 在2021年过期 而JSESSIONID cookie将在用户关闭浏览器之后过期

请求4
GET /support/login HTTP/1.1
Host: www.example.com
Cookie: "XXXX"; remusername=Nick
响应4
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Lenth: 56823

URL中的会话ID
=========================================================================
---在JSP中使用EL(表达式语言)
EL表达式最初源自于JSTL的一部分
EL表达式不能用在任何指令中 还有JSP的声明 脚本 或者表达式 除此之外 EL表达式可以添加到
任意位置(JSP标签中也可以)
${ empty x } 如果x为空或者null 那么这个表达式的结果将为真 否则为假
${ x = y + 3 } 如果y是4 这个表达式的值就是7
${ x = y + 3; object.callMethod( x ); 'Hello, World!' } 在表达式使用多个表达式 但是只有最后一个
表达式的值会被保留下来 所以这个表达式的结果是 Hello, World!
${"aaaa"}和${'aaaa'}是等价的 都是字符串字面量 但是最好少用 会引发冲突

---对象属性和方法
${ shirt.size } 调用了Shirt的一个JavaBean类的getSize() 等价 ${ shirt["size"] } ${ shirt.getSize() }

---EL函数
${ fn:length( Object ) } 返回length
${ fn:toLowerCase( String ) } 将字符串变为小写(或者大写 toUpperCase)
${ fn:trim( String ) } 去除字符串两端的空白

---EL操作集合
对Map
${ map["username"] } //Jonathon
${ map["userId"] } //27
或者
${ map.username}
${ map.userId }

对List
${ list[0] } 或者 $[ list["0"] ]
集合和队列 不能通过EL访问

---在EL表达式中使用作用域变量
EL解析变量的流程
1.检查该变量是否属于隐式变量
2.如果不在11个隐式变量之中 求值程序将在页面作用域寻找PageContext.getAttribute( "variable" )
4.如果没有找到 求值程序接着寻找同名的请求特性(HttpServletRequest.getAttribute( "variable" ))
5.如果没有找到 寻找同名的会话特性 HttpSession.getAttribute( "variable" )
6.如果没有找到 寻找同名的应用特性 ServletContext.getAttribute( "variable" )
7.如果还是没有找到 报错

---隐式变量
1.pageContext (唯一一个不是Map的隐式EL变量)
2.pageScope 3.requestScope 4.sessionScope 5.applicationScope 6.param 7.paramValue(多个请求值) 8.header 9.headerValues 10.initParams 11.cookie

使用例子
Remote Address: ${ pageContext.request.remoteAddr } <br/>
Request URL: ${ pageContext.request.requestURL } <br/>
Session ID: ${ pageContext.request.session.id } <br/>
Application Scope: ${ applicationScope[ "appAttribute" ] } <br/>
Page Scope: ${ pageScope[ "pageAttribute" ] } <br/>
Session Scope: ${ sessionScope[ "sessionAttribute" ] } <br/>
Request Scope: ${ requestScope[ "requestAttribute" ] } <br/>
User Parameter: ${ param[ "user" ] } <br/>
Color Multi-Param: ${ fn:join(paramValues[ "colors" ], ', ') } <br/>
Accept Header: ${ header[ "Accept" ] } <br/>
Session ID Cookie Value: ${ cookie[ "JSESSIONID" ].value } <br/>

http:/localhost:8080/info.jsp?user=jack&colors=green&colors=red
Remote Address: 127.0.0.1
Request URL: http:/localhost:8080/info.jsp
Session ID: E42FAA12E78F00EF4EF6767C3450E11F
Application Scope: foo
Page Scope: bar
Session Scope: sand
Request Scope: castle
User Parameter: jack
Color Multi-Param: green, red
Accept Header: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/'*';q=0.8
Session ID Cookie Value: E42FAA12E78F00EF4EF6767C3450E11F

---<%--@elvariable id="user" type="com.wrox.User"--%>
加了这一句 在IDE中 你用user有代码提示和智能建议 他告诉IDE 在本页的隐式作用域中有一个
user变量
Username: ${user.username}
UsernameLength: ${user.username.length()}

---URI的那一串URL地址 只是对应的一个.tld文件 在游览器中访问也是404的

---这里provided 是因为tomcat已经包含了Servlet api库 因此不需要将它们包含在部署的应用程序中
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

---核心标签库(C命名空间)
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
包括条件编程工具 循环和迭代以及输出内容

<c:out>和EL区别 <c:out>这个默认等同于${ fn:escapeXml(someVariable) } 对保留的XML字符转义
< c:out > < c:out value="${someVariable}" default="Value not specified." />
default属性 指定当value为null时使用的默认值

也可以<c:out value="${someVariable}"> default value </c:out> 这样 可以使用HTML标签 js和其他
JSP标签生成默认值

---
<c:url value="http://www.example.net/content/news/today.jsp">
    <c:param name="story" value="${stroyId}" />
    <c:param name="seo" value="${seoString}" />
</c:url>
在URL中添加查询参数
<a href="<c:url vlaue="/view.jsp">
    <c:param name="formId" vlaue="12" />
</c:url>">Product Forum</a>
被部署到/boards 链接到/boards/view.jsp?forumId=12 部署到/forums 链接指向/forumId/view.jsp?forumId=12

默认<c:url>标签把结果URL输出到响应中 如果某个URL需要在页面中使用多次 可以放到作用域
变量中 var指定了用于创建和保存结果的URL的EL变量名称 默认它被保存为页面作用域
<c:url value="/index.jsp" var="homepageUrl" scope="request" />

---
<c:if test="${something == somethingElse}" var="itWasTrue">
    execute only if test is true
</c:if>
<c:if test="${itWasTrue}">

var="itWasTrue"可选 将它保存为变量 在页面中多次使用它的结果

对于if/else 是用choose的
 

<c:choose>
    <c:when test="${something}"> if </c:when>
    <c:when test="${something}"> else if </c:when>
 ... <c:otherwise> else </c:otherwise>
</c:choose>

---

<c:forEach var="i" begin="0" end="100" step="3">
 Line ${i} </c:forEach>

<c:forEach items="${users}" var="user">
 ${user.lastName}, ${user.firstName} </c:forEach>

这个相当于 for (User user : users)
items中的表达式必须是一些集合或数组

---<c:redirect>

<c:redirect url="http://www.example.com/" />

<c:redirect url="/ticket">
    <c:param name="action" value="view">
    <c:param name="ticketId" value="${ticketId}">
</c:param>
<c:redirect uri="/browse" context="/store" />

---国际化和格式化标签库(FMT命名空间)(jstl的)

---用户的请求会引发Servlet容器调用一个Servlet的service方法 并给这个方法传入一个ServletRequest实例和一个ServletResponse实例 分别封装了HTTP请求和响应 Servlet还为每个应用程序创建一个ServletContext实例 封装context(应用程序)的环境细节 每个Servlet还有一个封装Servlet配置信息的ServletConfig

---Servlet接口有5个方法
void init(ServletConfig config)
void service(ServletRequest req, ServletResponse res)
ServletConfig  getServletConfig()
java.lang.String getServletInfo()
void  destroy()

---一个应用程序中的所有用户 共用一个Servlet实例 因此不建议使用类级变量

---Servlet初始化Servlet的时候 Servlet容器将ServletConfig传给Servlet的init方法

---ServletContext表示Servlet应用程序 每个Web应用程序只有一个context 在分布式环境中 一个应用程序同时部署到多个容器中 并且每台Java虚拟机都一个ServletContext对象
ServletConfig中调用getServletContext可获得

---public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {}
写servlet类继承GenericServlet 有一个无参的init 和一个ServletConfig成员变量 用这个就不用亲自保存ServletConfig 但是 真正实用的是HttpServlet

---利用隐藏域保持状态 把值放在HTML表单的隐藏域中 当用户提交表单的时候 隐藏域中的值也传送到服务器 只有当传递的信息不需要跨越多个页面才适合使用

---public abstract class HttpServlet extends GenericServlet{}
protected void  doDelete(HttpServletRequest req, HttpServletResponse resp)
protected void  doGet(HttpServletRequest req, HttpServletResponse resp)
protected void  doHead(HttpServletRequest req, HttpServletResponse resp)
protected void  doOptions(HttpServletRequest req, HttpServletResponse resp)
protected void  doPost(HttpServletRequest req, HttpServletResponse resp)
protected void  doPut(HttpServletRequest req, HttpServletResponse resp)
protected void  doTrace(HttpServletRequest req, HttpServletResponse resp)
protected long  getLastModified(HttpServletRequest req)
protected void  service(HttpServletRequest req, HttpServletResponse resp)
void  service(ServletRequest req, ServletResponse res)

---Interface ServletRequest
java.lang.Object  getAttribute(java.lang.String name)
java.util.Enumeration<java.lang.String> getAttributeNames()
java.lang.String  getCharacterEncoding()
int getContentLength()
long  getContentLengthLong()
java.lang.String  getContentType()
DispatcherType  getDispatcherType()
ServletInputStream  getInputStream()
java.lang.String  getLocalAddr()
java.util.Locale  getLocale()
java.util.Enumeration<java.util.Locale> getLocales()
java.lang.String  getLocalName()
int getLocalPort()
java.lang.String  getParameter(java.lang.String name)
java.util.Map<java.lang.String,java.lang.String[]>  getParameterMap()
java.util.Enumeration<java.lang.String> getParameterNames()
java.lang.String[]  getParameterValues(java.lang.String name)
java.lang.String  getProtocol()
java.io.BufferedReader  getReader()
java.lang.String  getRealPath(java.lang.String path)
java.lang.String  getRemoteAddr()
java.lang.String  getRemoteHost()
int getRemotePort()
java.lang.String  getScheme()
java.lang.String  getServerName()
int getServerPort()
ServletContext  getServletContext()
boolean isAsyncStarted()
boolean isAsyncSupported()
boolean isSecure()
void  removeAttribute(java.lang.String name)
Removes an attribute from this request.
void  setAttribute(java.lang.String name, java.lang.Object o)
void  setCharacterEncoding(java.lang.String env)

---Interface ServletResponse
void  flushBuffer()
int getBufferSize()
java.lang.String  getCharacterEncoding()
java.lang.String  getContentType()
java.util.Locale  getLocale()
ServletOutputStream getOutputStream()
java.io.PrintWriter getWriter()
boolean isCommitted()
void  reset()
void  resetBuffer()
void  setBufferSize(int size)
void  setCharacterEncoding(java.lang.String charset)
void  setContentLength(int len)
void  setContentLengthLong(long length)
void  setContentType(java.lang.String type)
void  setLocale(java.util.Locale loc)

---Interface ServletConfig
java.lang.String  getInitParameter(java.lang.String name)
java.util.Enumeration<java.lang.String> getInitParameterNames()
ServletContext  getServletContext()
java.lang.String  getServletName()

---Interface ServletContext

---Interface HttpSession
java.lang.Object  getAttribute(java.lang.String name)
java.util.Enumeration<java.lang.String> getAttributeNames()
long  getCreationTime()
java.lang.String  getId()
long  getLastAccessedTime()
int getMaxInactiveInterval()
ServletContext  getServletContext()
java.lang.String[]  getValueNames()
void  invalidate()
boolean isNew()
void  removeAttribute(java.lang.String name)
void  setAttribute(java.lang.String name, java.lang.Object value)
void  setMaxInactiveInterval(int interval)

---Class Cookie
java.lang.String  getComment()
java.lang.String  getDomain()
int getMaxAge()
java.lang.String  getName()
java.lang.String  getPath()
boolean getSecure()
java.lang.String  getValue()
int getVersion()
boolean isHttpOnly()
void  setComment(java.lang.String purpose)
void  setDomain(java.lang.String pattern)
void  setHttpOnly(boolean httpOnly)
void  setMaxAge(int expiry)
void  setPath(java.lang.String uri)
void  setSecure(boolean flag)
void  setValue(java.lang.String newValue)
void  setVersion(int v)

---Interface HttpServletRequest 继承ServletRequest 增加了几个方法
Cookie[]  getCookies()
java.lang.String  getHeader(java.lang.String name)
java.util.Enumeration<java.lang.String> getHeaderNames()
java.util.Enumeration<java.lang.String> getHeaders(java.lang.String name)
java.lang.String  getMethod() //for example, GET, POST, or PUT.
java.lang.String  getQueryString()
HttpSession getSession()

---Interface HttpServletResponse
void  addCookie(Cookie cookie)
void  addHeader(java.lang.String name, java.lang.String value)
void  sendRedirect(java.lang.String location)

---过滤器像栈一样 先进去 再返回 所以过滤器可以在Servlet处理请求的前后执行某些操作 过滤器可以映射到URL或者Servlet 通过使用URL 我们不止可以拦截Servlet的请求 还可以拦截图片 CSS文件 js文件等
一个过滤验证器

public class AuthenticationFilter implements Filter { @Override public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException { HttpSession session = ( ( HttpServletRequest ) request ).getSession( false ); if ( session == null || session.getAttribute( "username" ) == null ) { ( ( HttpServletResponse ) response ).sendRedirect( "login" ); } else
 { chain.doFilter( request, response ); } } @Override public void init ( FilterConfig config ) throws ServletException {} @Override public void destroy () {} }

---用编程的方式配置filter

@WebListener public class Configurator implements ServletContextListener { @Override public void contextInitialized ( ServletContextEvent event ) { ServletContext context = event.getServletContext(); FilterRegistration.Dynamic registration = context.addFilter( "loggingFilter", new LoggingFilter() ); registration.addMappingForUrlPatterns( EnumSet.of( DispatcherType.REQUEST, DispatcherType.INCLUDE, DispatcherType.FORWARD, DispatcherType.ERROR ), false, "/*"
 ); registration = context.addFilter( "authenticationFilter", new AuthenticationFilter() ); registration.addMappingForUrlPatterns( null, false, "/tickets", "/chat", "/sessions"
 ); } @Override public void contextDestroyed ( ServletContextEvent event ) {} }

---监听器

@WebListener public class SessionListener implements HttpSessionListener, HttpSessionIdListener { private static final Logger log = LogManager.getLogger(); @Override public void sessionCreated ( HttpSessionEvent e ) { log.debug( "Session " + e.getSession().getId() + " created." ); SessionRegistry.addSession( e.getSession() ); } @Override public void sessionDestroyed ( HttpSessionEvent e ) { log.debug( "Session " + e.getSession().getId() + " destroyed." ); SessionRegistry.removeSession( e.getSession() ); } @Override public void sessionIdChanged ( HttpSessionEvent e, String oldSessionId ) { log.debug( "Session ID " + oldSessionId + " changed to " + e.getSession().getId() ); SessionRegistry.updateSessionId( e.getSession(), oldSessionId ); } }
---Session的一些东西
public final class SessionRegistry { private static final Map< String, HttpSession > SESSIONS = new Hashtable<>(); private SessionRegistry () {} public static void addSession ( HttpSession session ) { SESSIONS.put( session.getId(), session ); } public static void updateSessionId ( HttpSession session, String oldSessionId ) { synchronized ( SESSIONS ) { SESSIONS.remove( oldSessionId ); addSession( session ); } } public static void removeSession ( HttpSession session ) { SESSIONS.remove( session.getId() ); } public static List< HttpSession > getAllSessions () { return new ArrayList<>( SESSIONS.values() ); } public static int getNumberOfSessions () { return SESSIONS.size(); } }

你可能感兴趣的:(Java Web高级编程(基础))