JavaEE复习笔记
根据上课的笔记整理与补充。涵盖web应用开发基础,jsp,标签,注解,struts,spring, mvc, 数据访问等内容
(因为转于个人blog,csdn图片无法显示,可至下面链接查看https://sakuyui.github.io/2019/12/27/JavaEE%E5%A4%8D%E4%B9%A0%E7%AC%94%E8%AE%B0/)
contact: 405544641@qq.com
Spring的思想 控制翻转:让容器管理对象的创建与销毁,依赖注入:利用反射实现,动态地向一个对象提供其所需的其他对象
JavaEE三大组件: Servlet, Filter, Listener
组件必须有 init(conf) destroy()
web容器(servlet容器)
请求怎么来到servlet呢?答案是servlet容器,比如我们最常用的tomcat,同样,你可以随便谷歌一个servlet的hello world教程,里面肯定会让你把servlet部署到一个容器中,不然你的servlet压根不会起作用。
tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。
import javax.servlet servlet是个接口
HttpServlert实现Servlet
使用Servlet ServletRequest ServletRespond
1.首先要在web.xml中进行配置
<servlet>
<servlet-name>A</servlet-name> //servlet名
<servlet-class>com.xxx.xx.xx.servlet类名</servlet-class> //对应的类
<init-param> //初始化参数
<param-name>p1</param-name><param-value>123</param-value>
</init-param>
</servlet>
//! 到这为止已经定义好servlet,不会有任何错误。 当服务器启动后,也会创建好servlet. 但是无法访问因为没mapping
<servlet-mapping>
<servlet-name>A</servlet-name> //要和上面对应
<url-pattern>/login</url-pattern> //注意 /代表的是web Content的位置
</servlet-mapping>
**url-pattern: /是缺省匹配,若当前访问资源地址的所有 Servlet 都不匹配时,就由缺省的 Servlet 进行处理
优先级:全路径匹配>部分路径匹配>拓展名匹配
如果我们web应该中同时配置"/"和"/*",那么默认的Servelt永远都不会被匹配到,所有的路径最终都会匹配到"/*"上
/不能匹配jsp,原因是jsp容器已经默认映射了一个*.jsp,优先级要高于/ /*可以
精确路径匹配>最长路径匹配>扩展匹配 /a/*.xxx 这样方式会报错。不能混搭。
注:Filter不会像servlet只匹配一个。 顺序与定义顺序相同
/*和/** 后者会匹配更多的目录 (Ant path匹配。spring支持。还支持正则表达式,进行更复杂的匹配)
关于url-pattern的/, 同样在struts中,默认映射了*.action *.do , /无法覆盖他们
strut2的配置文件加载顺序为:
Struts-default.xml---> struts-plugin.xml--> struts.xml--> struts.properties--> web.xml
使用servlet
//AServlet.java
package a; //倒序 com.xxx,部门,项目:模块
先引入这3个包
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class AServlet extends HttpServlet{
/* 默认已经实现
private ServletConfig config;
@Ovrride
public void init(ServletConfig config) throws ServletException{
super(config);
init();
}*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException{
response.setContentType("text/html;charset=UTF-8"); //默认ISO8859-1
response.setCharacterEncoding("UTF-8")//设置编码
PrintWriter out=response.getWriter();
out.println("<h1>this is servlet</h1>");
//不要close() 谁创建的流谁负责关闭
}
@Ovrride
protected void doPost(HttpServletRequest request,HttpServletResponse){
}
/*
@Override
public void destroy(){
super.destroy();
}
@Override
public void service(SevletRequest req,ServletResponse res) throws ServletException,IOException{
res.setContextType("text/html");
PrintWriter out=response.getWriter();
out.println("this is servlet");
//获取config
//getServletConfig();
//!!!!考ServletConfig 的函数
HttpServletRquest hsr=(HttpServeltRequest) req;
HttpServletResponse hsres=(HttpServletResponse) res;
//GET / HTTP/1.1\r\n 获取资源
//GET /HTTP/a HTTP/1.1\r\n
String method=res.getMethod();
if(method.compareTo("POST")==0){
doPost(req,res);
}else if("GET".equals(method)){
doGet(req,res);
}
}
*/
}
注意事项
-
doPost doGet serice 一般抛2个异常 ServletException 和IOException
-
serve的两个参数是ServletRequest和ServletResponse
-
Context-Type:
-
- text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
- text/html : HTML格式
-
用this.getServletConfig().getInitParameter(String); 获取servlet的初始化参数
每个servlet有一个servletconfig,但是全局只有一个servletcontext (每个web应用仅有一个,servletcontext也可以叫applicationContext,是最大的web域对象)
使用**response.setContentType(String);**设置 如text/html;charset=UTF-8
- 输出办法: 首先从response.getWriter();获取PrintWriter对象,之后利用其进行流操作输出 (println();)
- HttpServlet 中已存在 service()方法.缺省的服务功能是调用与 HTTP 请求的方法相应的 do 功能。
例如,如果 HTTP 请求方法为 GET,则缺省情况下就调用 doGet()。 super(req,res)
setContentType(String) 和 setCharacterEncoding()的区别:前者设置的是页面的静态文字编码(浏览器显示的编码),后者关系到动态参数的编码
HTTP缓存**(必考)**
-
http缓存有强缓存,协商缓存
+步骤1. 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加在缓存中的资源,并不会将请求发送到服务器。 (返回200)
2.如果未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可以使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。
3.如果未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。 -
强缓存: 利用http的返回头中的Expires或者Cache-Control两个字段来控制的。前者表示缓存过期时间(具体时间),后者表示相对时间。如Cache-Control:3600,代表着资源的有效期是3600秒。所以服务器与客户端时间偏差也不会导致问题。
同时启用的时候Cache-Control优先级高 -
- Cache-Control可包含的字段:
1.max-age 单位s
2.s-maxage 同1,只适用于共享缓存,私有缓存中被省略
3.public 响应可以被任何对象缓存
4.private 响应只能被单个用户,非共享。不能被代理服务器缓存
5.**no-cache:**强制缓存了响应的用户,在使用数据前都要先发请求到服务器
6.no-store:禁止缓存
- Cache-Control可包含的字段:
-
协商缓存:
服务器根据http头信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match来判断是否命中协商缓存。如果命中,则http返回码为304,浏览器从缓存中加载资源。
Last-Modify/If-Modify-Since
ETag/If-None-Match
与Last-Modify/If-Modify-Since不同的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag可以保证每一个资源是唯一的,资源变化都会导致ETag变化*。ETag值的变更则说明资源状态已经被修改。服务器根据浏览器上发送的If-None-Match值来判断是否命中缓存。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95XD8hDL-1577506046387)(./1576666287803.png)]
ServletRequest
>>getAttribute(String) //获取存在request的属性 是Object
>>getAttributeNames() //Enumeration 用hasMoreElements() nextElement()进行遍历
>>getParameter(String)//获取存在request的参数 只能是String (可以获得通过get post传进来的数据)
>>getParameterNames() //返回迭代器
>>getParameterValues() //返回String[]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89nEmyji-1577506046388)(./1576668415360.png)]
>>getProtocol()
>>getRealPath(String path) //寻找某个资源在服务器文件系统上的实际地址
>>getServletContext()
HttpServletResponse
>>addCookie(Cookie cookie)
>>getHeader(String name)
>>addHeader(String name, String value)
//继承来的
>> getWriter()
>>setContentType(String type)
- ServletConfig getServletConfig(); //必考
ServletConfig
- getInitParameter(String name)
- getServletName()
- getServletContext()
!!! 必考ServletContext
context可以直接在servlet里get,也可以从request.getSession().getServletContext() 也可以 request.getServletContext();
servletcontent.getRealPath("/")和servletcontent.getContextPath()的区别
前面是获取ServletContext 所在的文件系统上的实际位置。 后者是获取配置的servletContext路径
ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
凡是域对象都有如下3个方法:
**setAttribute(name,value);**name是String类型,value是Object类型;
往域对象里面添加数据,添加时以key-value形式添加
getAttribute(name);
根据指定的key读取域对象里面的数据
removeAttribute(name);
根据指定的key从域对象里面删除数据
同时因为都是web域对象。所以除servletcontext外,**其他三个域都能通过getServletContext()**获取到servletContext
可以获取web.xml中的全局参数
<context-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</context-param>
用servletContext.getInitParameter(parameName);获取
>>getContextPath();
设置contextpath的方式
/META-INF/context.xml
!!可以获取servletContext()的方式
- ServletConfig的getServletContext()
- request.getSession().getServletContext()
- 直接 getServletContext();
WEB应用结构
xxxxxxxxxxxx\first
-> WEB-INF
----> classes
----> lib
----> web.xml
-> META-INF
----> context.xml
!!!URL 三部分
1.schema 2.服务器位置 3.资源路径
<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>
header
http的两部分内容:header body ,header项用\r\n区分,区分 两次回车换行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c8EoNWPb-1577506046394)(./1576751175527.png)]
编码 base64:3个字节为一组 ucs:任何一个字符都是4字节
http状态码:
404 资源不存在
500 服务器遇到外部故障,一般是异常
2xx OK
3xx 重定向
4xx 客户端错误
–>401 客户端证书无效
–>403 请求结构正确。但是服务器不想处理.403暗示了所请求的资源确实存在。跟401一样,若服务器不想透露此信息,它可以谎报一个404
–>405 请求方法错误。比如用了不支持的协议,或者不支持get,结果用了get
5xx:服务器端错误
502 代理错误
500 异常
501 服务器不能识别一个方法。类似405,但是405是能够被服务器识别,但是资源不支持该方法.
101表示服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。
web.xml
<welcome-file-list> //可以设置多个,可以访问到web-inf内的文件,会返回第一个找到的文件,找不到就404,首页的路径只能是一个实际存在的物理文件地址,不能将首页设置成Servlet或Controller的地址,再通过来Servlet或Controller返回一个页面
<welcome-file>a.jsp</welcome-file>
<welcome-file>b.html</welcome-file>
<welcome-file>c.html</welcome-file>
</welcome-file-list>
xml区分大小写
部署web application在Tomcat
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- 部署 "三个" web application -->
<Context path="/a" docBase="/somefoler/first"/> //虚拟路径1 context path=/a
<Context path="/s" docBase="/otherfolder/second"/> //虚拟路径2 context path=/s
<Context path="" docBase="/otherfolder/second"/> //虚拟路径3
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
**!!如何自己设计ServletContext().getRealPath(); **
A: ServletContext().getContextPath();可以用,然后去tomact的 server.xml中寻找对应docBase…然后就可以get到了,如果docBase是相对路径的话,也可以根据tomcat所在路径加上这个相对位置确定
//使用真实路径读取文件
String filename = getServletContext().getRealPath("/WEB-INF/aFolder/a.txt");
FileInputStream fis = new FileInputStream(filename);
###web socket
现在前后端通讯的常用的方式有ajax,websocket,还有fetch
//创建套接字
Socket s = new Socket("www.baidu.com", 80); //这是Java的Socket建立过程。直接访问底层的TCP协议。
var socket = new WebSocket("ws://localhost:8080/websocket1/b"); //JavaScript代码。
websocket可以跨域访问。非常灵活。
Connection: Upgrade
Cookie: JSESSIONID=6FFBEA8EB6951EAD7D123A2D7ED70861
Host: localhost:8080
Origin: http://localhost:8080
Sec-WebSocket-Key: 6ZxylD/4f4qccKeapm3LEQ==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
响应代码:101,不是200, 101表示服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。
在发送完这个响应最后的空行后,服务器将会切换到 在Upgrade消息头中定义的那些协议。: 只有在切换新的协议更有好处的时候才应该采取类似措施。
例如,切换到新的HTTP版本比旧版本更有优势,或者切换到一个实时且同步的协议以传送利用此类特性的资源。
Connection: upgrade
Date: Thu, 12 Sep 2019 00:54:07 GMT
Sec-WebSocket-Accept: 5uiTO0X9qutU+74Ugp/7eMHoXQk=
Upgrade: websocket
和以往的http请求不同,增加了Connection: Upgrade, Upgrade: websocket等请求头,大家理解,客户端请求建立websocket.
服务器可以不支持。当然,客户端程序来自同一个服务器,在某个使用websocket的应用中,显然支持。我们的JavaEE版本8支持websocket.
至于请求中的Sec-WebSocket-Key, 是base64编码,源数据是16个字节的随机数。服务器收到这个数据, 并不做Base64解码,而是直接拼上一个magic字符串,
“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”, 然后转换为utf-8编码的字节数组,最后做SHA1,(见MD5,CRC,SHA-1,SHA-256)。
对SHA1产生的20个字节(160个比特位)做BASE64,然后就是Sec-WebSocket-Accept: 5uiTO0X9qutU+74Ugp/7eMHoXQk=, 返回给客户端。
客户端当然做同样的算法,然后做比对,实际上就是完成websocket的握手过程。
握手完毕,http协议“转换”到websocket协议。
- 1、客户端:申请协议升级
- 2.服务端:响应协议升级 :状态代码101表示协议切换。到此完成协议升级,后续的数据交互都按照新的协议来。
- 3、Sec-WebSocket-Accept的计算 :Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hTQfhJJL-1577506046395)(./1576755405347.png)]
实例:
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
//javaee
@ServerEndpoint("/chatroom/{roomId}/{nickName}")
public class ChatRoomServer{
@OnOpen//连接打开时
public void onOpen(Session session,@PathParam("roomId") long roomId,
@PathParam("nickName") String unDecName){
} //可以注入参数
@OnMessage //消息抵达
public void onMessage(Session session, String message, @PathParam("roomId") long roomId,
@PathParam("nickName") String unDecName)
{
}
@OnClose
public void onClose(Session session, @PathParam("roomId") long roomId,
@PathParam("nickName") String unDecName)
{}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gbJcKWAU-1577506046397)(./1576755801639.png)]
package a;
//Socket客户端
import java.io.*;
import java.net.*;
import javax.websocket.*;
@ClientEndpoint
public class WebSocketClienet {
//就是例子代码,只有一个session
public static Session session = null;
@OnOpen
public void onOpen(Session session) {
try {
this.session = session;
System.out.println("create a session.");
session.getBasicRemote().sendText("hello");
System.out.println("send hello to server.");
} catch (IOException ex) {
}
}
@OnMessage
public void processMessage(Session session, String message, boolean last) {
System.out.println(message);
}
@OnClose
public void end() {
System.out.println("bye server.");
}
@OnError
public void onError(Throwable t) throws Throwable {
System.out.println("meet some exception in client.");
t.printStackTrace();
}
public static void main(String[] args) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(WebSocketClienet.class, URI.create("ws://localhost:8080/websocket1/b"));
for(int i = 0; i < 10; i++) {
Thread.sleep(1000);
session.getBasicRemote().sendText("" + new java.util.Date());
}
session.close();
}
}
####Server Sent Event(SSE):服务器向客户端发送消息 (应该是只做了解)
一般服务器向客户端发送消息常用的方式就是用setInterval去做轮询或者是websocket。只是前者setInterval**(//每60秒执行myFunction()一次 setInterval(“myFunction()”,60000); )**轮询这个中间的时间间隔需要考虑好,如果事件间隔较短,这对服务器的压力比较大,如果事件较长,则有些需要立即立即做出响应的方式是做不到的。后者的websocket相对来说技技术要求有点高,实现起来比较复杂。所以就有现在的这种方式就是Server-sent Events我们只需要需要在服务器端将事件流发送给前端,然后前端接收到后端所传给的事件流,然后触发事件,这是事件的捕获和监听其实和前端的事件捕获和触发是一样的
用法:
var evtSource = new EventSource('/sse'); //创建es对象,/sse是服务器端给的向前端发送事件的接口地址。通过get方式进行发送事件。
//var evtSource = new EventSource('http://www.baidu.com', { withCredentials: true }); (如果跨域)
//至此接收器创建好了
evtSource.onmessage = function (e) {
console.log(e.data)
}
//也就是当后端发送的内容之后就会进行触发,并且将data给打印出来,首先要提出的的是,Server-sent Events 所发送的内容都是字符串的流而且是通过utf-8的编码格式的,如果后端希望给前端发送一串json,也需要将json转化成相对应的字符串,然后在发送给前端,前端接收之后,再讲所发送的字符串转换成json,然后进行处理。
//然后就是监听后端发送给前端的事件内容,不如说,我们后端给前端sent一个testEvent事件,前端通过事件接收者,去触犯相对应的事件监听,因此就有了下面的工作流程
evtSource.addEventListener('testEvent', function (e) {
console.log(e)
})
...
后端应该如何才能给我们发送事件呢,
首先我们发送内容是需要给前端设置一个mime为text/event-stream,然后在进行发送事件的内容
'Content-Type': 'text/event-stream'
- 注解@Endpoint("/b") // @ServerEndpoint("/b")指定服务器资源
- sse使用 javax.socket.endpoint
javax.websocket.Endpoint类
使用方法。一个类继承Endpoint,之后重写onOpen,onClose,onError
对于Socket来说,每一端都是一个EndPoint
还可以具体一点,用ServerEndpoint或者ClientEndpoint
Session 接口 (websocket的)
>> getBasicRemote() :返回RemoteEndpoint object,getAsyncRemote是非阻塞式的,getBasicRemote是阻塞式的
大部分情况下,推荐使用getAsyncRemote()。由于getBasicRemote()的同步特性,并且它支持部分消息的发送即sendText(xxx,boolean isLast). isLast的值表示是否一次发送消息中的部分消息,对于如下情况:
session.getBasicRemote().sendText(message, false);
session.getBasicRemote().sendBinary(data);
session.getBasicRemote().sendText(message, true);
由于同步特性,第二行的消息必须等待第一行的发送完成才能进行,而第一行的剩余部分消息要等第二行发送完才能继续发送,所以在第二行会抛出IllegalStateException异常。如果要使用getBasicRemote()同步发送消息,则避免尽量一次发送全部消息,使用部分消息来发送。
>>WebSocketContainer getContainer()
####WebSocketContainer
connectToServer(class,URI) ,返回Session
所以… session <-> WebSocketContainer 可以相互获取。 session是从container连接服务器后来的.
至于Endpoint,客户端和服务器都是一个Endpoint
###HttpSession
import javax.servlet.http.*;
其是一个域对象。因此也具有
getAttribute(String),setAttribute(String,Object)等函数
同时有getID(),**getServletContext()**等函数
创建时间 getCreationTime()
getMaxInactiveInterval() //超时时间
设置超时时间
在web.xml中
<session-config>
<session-timeout>2</session-timeout> //2分钟,默认为30
</session-config>
#也可以session.setMaxInactiveInterval(30*60);
- 扔到Attribute中的对象要序列化
Q:如何识别一个request是某个会话的
tomcat有个全局的map,产生的session对象的id一定放在**response中,返回给浏览器.**下次请求会带上它
一般来说Session是基于Cookie实现的,
会话追踪手段
-
手段1:cookies.
-
手段2: URL重写 如果浏览器不支持Cookie或用户阻止了所有Cookie,可以把会话ID附加在HTML页面中所有的URL上,这些页面作为响应发送给客户。这样,当用户单击URL时,会话ID被自动作为请求行的一部分而不是作为头行发送回服务器。这种方法称为URL重写(URL rewriting)。
-
手段3:隐藏域
使用隐藏域:<input type="hidden" name="…" value="…">
jsessionID ssessionID …
刷新是个问题
有时不用httpsession, 把会话信息放在分布式存储系统。只要ID在就行
####Cookies
response.addCookies(Cookies);
//Cookie(String name, String value)
压缩(要考)
gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRzVaPxo-1577506046399)(./1576837387364.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b23yqMS7-1577506046402)(./1576837550820.png)]
RequestDispatcher
可以用requestDispatcher来分发请求到多个组件去处理。
rd.forward() //转发,让其他组件去处理,自己不管了
rd.include(request,response) 包含.是让其他组件去处理,但是还会返回来,自己继续处理
!!Interface SingleThreadMode() //保证不会有多个线程执行service函数
解决并发访问的两种方法:
- 1.加锁
- 2.数据复制
事务的ACID
- A:原子性
- C:一致性
- I:隔离性
- D:持久性
**request.getContextPath(): ** 可以获取所配置的ServletContext路径
**例:**http://localhost:8080/dmsd-itoo-exam-log-web/course/index.jsp,在tomcat中配置了application context为 /dmsd-itoo-exam-log-web
request.getContextPath(),得到context路径:/dmsd-itoo-exam-log-web (取决于contextpath的配置);
request.getServletPath(),返回当前请求的资源相对于context的路径:/course/index.jsp;
request.getRequestURL(),返回请求资源的完整地址:http://localhost:8080/dmsd-itoo-exam-log-web/course/index.jsp;
request.getRequestURI() ,返回包含Context路径的资源路径:/dmsd-itoo-exam-log-web/course/index.jsp。
###Filter
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public mFliter implements Fliter{
private FliterConfig config;
public void destroy(){
}
public void doFliter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException,IoException{
chain.doFilter(req,res); //当前过滤器处理结束,往下一个过滤器
//多个过滤器会形成一个过滤器链,如果不想拦截下该请求的话,应该让Filter往下传,后面没有filter后就到达资源
//想拦截的话可以什么都不干,也可以直接跳到另一个地方(用redirect,forwer之类的
}
}
//Filter通常要做的事情:
//Filter最最最早执行。
//在资源到达后端之前就执行了。 也就是拦截器
//数据写在session里
//常见作用:1.认证 不拦截/login.html 2.日志 3.数据转换 4.数据压缩 5.加密 6
访问计时: 应该加在filter
getServletContext().log(“xxxxxxxxxxxx”);
乱码解决 (Filter不仅可以用来拦截不合法的请求,还可以用来编码转换)
request.setCharcterEncoding("UTF-8"); //可以用filter实现
String wd=new String(wd.getBytes("ISO-8859-1"),"UTF-8");
public class EncodingFilter(){
public void doFilter(...){
request.setCharacterEncoding("UTF-8");
chain.doiFliter