JavaEE学习笔记
LZC Lv4

JavaEE

doGet() 和 doPost()

doGet()

维基百科定义:

GET requests a representation of the specified resource.

Note that GET should not be used for operations that cause side-effects, such as using it for taking actions in web applications. One reason for this is that GET may be used arbitrarily by robots or crawlers, which should not need to consider the side effects that a request should cause.

GET请求指定资源的表示形式。

注意,GET不应该用于产生副作用的操作,比如在web应用程序中使用它来执行操作。这样做的一个原因是,GET可能会被机器人或爬虫任意使用,它们应该不需要考虑请求应该引起的副作用。

当浏览器使用get方式提交数据时,servlet需要提供doGet()方法。

明文显示:doGet方法在提交表单时会在url后面显示提交的内容(不安全)。

长度限制:doGet方法只能提交256个字符(1024字节),因为get方式数据的传输载体是URL(提交方式能form,也能任意URL链接)。

会用到get方式的情景:

  • form默认的提交方式
  • 如果通过一个超链访问某个地址
  • 如果在地址栏直接输入某个地址
  • ajax指定使用get方式的时候

关于GET方法还有一个称呼是幂等(idempotent)方法(无论操作多少次,结果一致)。

doPost()

维基百科定义:

POST submits data to be processed (e.g., from an HTML form) to the identified resource.
The data is included in the body of the request. This may result in the creation of a new resource or the updates of existing resources or both.

POST将待处理的数据(例如,来自HTML表单)提交给所标识的资源。
数据包含在请求的主体中。这可能会导致创建新资源或更新现有资源,或者两者都有。

当浏览器使用post方式提交数据的时候,servlet需要提供doPost()方法。

用于客户端传输数据到服务器端,也会有副作用。

隐藏数据:post方法使用表单传输,不会明文显示数据。

长度大:POST也是有长度限制的,不是一般说的POST不限制,默认是2097152,不同的Web Server实现不同。

会用到post方式的情景:

  • 在form上显示设置 method="post"的时候
  • ajax指定post方式的时候

在servlet文件中,由service(request, response) 方法功能是判断用户发出是什么请求,如果是get则调用子类(HttpSevr)的doGet方法,如果是post则调用子类(HttpSevr)的doPost方法。

区别

  • get方式采用URL跳转方式请求,post方法采用表单提交方式请求。
  • get请求会有cache,post不会有cache。
  • get请求会保留在浏览历史中,post不会。
  • get请求可以保存到书签(本质是个URL),post不能。
  • get请求长度小,post请求长度大。
  • get请求应该只用于获取数据,post请求处理敏感信息。

隐藏域

HTML表单隐藏域

隐藏域是用来收集或发送信息的不可见元素,对于网页访问者来说,隐藏域是不可见的。当表单被提交时,隐藏域就会将信息用设置时定义的名称和值发送到服务器。

使用方法

1
type="hidden"

用法

一般用于隐藏不希望用户看见的信息,在提交表单时,将伴随用户提交的请求将信息传送。用于存放在表单,被提交时需要提交却不需要显示的参数值的容器。


Referer——防盗链

Referer是HTTP请求requset header的一部分,当浏览器向web服务器发送请求的时候,头信息中就包含Referer

Referer的内容就是当前页面的上一页面

Referer其实是Referrer的错误拼写,发现错误时已经广泛使用,修改成本高,于是就将错就错了。

为什么使用Referer

referrer 英/ rɪˈfɜːrə /
nn.推荐人,上线;介绍人

Referer字段告诉了服务器,用户在访问当前资源之前的位置,用来用户跟踪。

一言以蔽之,你从哪来?

Referer的使用

Referer是一个可选字段。

浏览器的 JavaScript 引擎提供document.referrer属性,可以查看当前页面的引荐来源。注意,这里采用的是正确拼写。

空Referer的定义为 Referer="" || Referer=null

当没有上一请求地址时,Referer是空。

直接在浏览器的地址栏中输入一个资源的URL地址,这种方式请求不包含Referer。

允许Referer为空,则允许浏览器或者重定向直接URL访问资源;

不允许为空,则直接输入URL访问会被拦截。

在servlet中使用:

1
2
3
4
5
6
7
String referer = request.getHeader("Referer");
if (referer==null||"".equals(referer)||!referer.startsWith("http://localhost:8081")) {
response.sendRedirect("xxx.html");
return;
}
request.getRequestDispatcher("xxx.html").forward(request,response);


ServletContext

ServletContext称为servlet上下文

服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。

此对象全局唯一,且工程内所有servlet共享此对象,因此叫做全局应用程序共享对象

servletContext是一个域对象

域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据。

读取全局配置参数

1
2
3
4
5
//根据指定的参数名获取参数值
getServletContext().getInitParameter(name);

//获取所有参数名称列表
getServletContext().getInitParameterNames();

搜索当前工程目录下面的资源文件

1
2
3
4
5
6
7
8
//根据相对路径获取服务器上资源的绝对路径
getServletContext().getRealPath(path);

//根据相对路径获取服务器上资源的输入字节流
getServletContext().getResourceAsStream(path);

//获取当前工程名字
getServletContext().getContextPath();

会话跟踪(session tracking)

session 英/ ˈseʃ(ə)n /

n.(某项活动的)一段时间,一场;(议会等的)会议,(法庭的)开庭;学年,上课时间;(酒吧中)演奏会(尤指演奏爱尔兰音乐);(尤指录音师的)灌录音乐时间;<非正式>酗酒期;基督教长老会的管理机构

adj.(音乐家)伴奏的

[计算机]会话

HTTP是一种无连接的协议,如果客户端只是单纯请求一个文件,服务器端对其响应,无需知道一系列的请求是否来自同一客户端,也无需担心客户端是否处于连接状态,简单来说,有人请求就直接响应,服务器不会保留之前客户端请求的任何记录。

因此这种通信协议使得服务器端难以判断所连接的客户端是否是同一个。

当进行Web程序开发时,需要将相关的请求结合,并维持用户的状态在服务器上,因此引出会话追踪(session tracking)对同一用户对服务器的连续的请求和接受响应的监视

会话跟踪技术:

  • Cookie
  • Session
  • URL重写
  • 隐藏表单域

cookie 英/ ˈkʊki /

*n.*曲奇饼,小甜饼;……样的人;(浏览网页后存储在计算机的)缓存文件;<苏格兰>淡面包;漂亮的年轻女子

Cookie,它的名字源自一种叫 Fortune cookie 的“幸运小饼干”,这种饼干里面有一张小纸条。

注意:Cookie只支持Ascii字符形式并且不能跨浏览器使用。

Cookie是什么?

一些数据信息,类型为小型文本文件,存储于电脑上的文本文件中。

Cookie有什么用?

例如登陆过的网站,再次打开就会自动登录。

浏览器保存了我们的Cookie,里面记录了一些信息,当下一次浏览器向Web服务器发送任何请求时,浏览器会把这些Cookie信息发送到服务器,服务器使用这些信息识别用户。

Cookie怎么用?

创建Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CookieServletOne extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 创建Cookie
Cookie cookie = new Cookie("author","cicada");
// 设置生命周期 1小时
cookie.setMaxAge(60*60);
// 将Cookie添加进Response
response.addCookie(cookie) ;
response.getWriter().print("Hello:Cookie");
}
}

获取Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CookieServletOne extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doPost...");
// 创建Cookie数组接收
Cookie[] cookies = request.getCookies() ;
// 遍历接收到的Cookie
for (Cookie cookie:cookies){
System.out.println("Name:"+cookie.getName());
System.out.println("Value:"+cookie.getValue());
}
response.setContentType("text/html;charset=utf-8");
String userName = request.getParameter("userName") ;
response.getWriter().print("Hello:"+userName);
}
}

更新Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CookieServletTwo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 创建Cookie
Cookie cookie = new Cookie("author","smile");
// 设置生命周期 2小时
cookie.setMaxAge(60*60*2);
response.addCookie(cookie) ;
response.getWriter().print("Hello:Cookie");
}
}

删除Cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CookieServletTwo extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Cookie[] cookies = request.getCookies() ;
for (Cookie cookie:cookies){
if (cookie.getName().equals("author")){
// 将生命改为0就表示该Cookie被作废了
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
String userName = request.getParameter("userName") ;
response.getWriter().print("Hello:"+userName);
}
}

Cookie相关接口

  • setMaxAge() :设置cookie过期的时间,单位为秒。
  • getMaxAge() :获取cookie的最大生命周期
  • getName() :获取cookie的名称。名称在创建后不能改变。
  • getValue() :获取与cookie关联的值。
  • setValue() :设置与cookie关联的值。

Session

Cookie的好兄弟

session是什么?

session在Web应用中称为会话控制,是服务器为了保存用户状态而创建的一个对象,用于存储信息。

cookie存储在用户端,session存储在服务器端。

session有什么用?

由于cookie不能存放大量数据,这时出现了一种新的技术,Session。

session是存储在服务器端的特殊对象,服务器会为每一个浏览器(客户端)创建一个唯一的session。

session是服务器端共享,每个浏览器(客户端)独享的。可以在session存储数据,实现数据共享。

session怎么用?

存储在服务器的数据会更加的安全,不容易被窃取,并且session比Cookie使用方便,Session可以存储对象,Cookie只能存储字符串,并且tomcat8.x之后的版本中Cookie可以存储的字符类型有限制。

最常使用的session是javax.servlet.http.HttpSession

获取HttpSession对象

1
HttpSession session = request.getSession(boolean create);

得到一个HttpSession对象。

如果当前请求不属于任何会话,并且create为true,则创建一个会话,否则返回null;如果为false,则与不带参数的形式等价。

Session的实现依赖于Cookie

每个Session对象都有一个唯一的JSESSIONID,会以Set-cookie响应头的形式将JSESSIONID返回给客户端,客户端再次访问的时候将JSESSIONID发送给服务器。后续请求时,服务器可通过JSESSIONID找到对应的Session对象。

这个JSESSIONID就是SessionId

HttpSession的方法

HttpServletRequestServletContext一样,它们都是域对象,HttpSession也是域对象,范围是当前对话

凡是域对象,都有如下四个操作对象的方法:

1
2
3
4
5
6
7
8
9
10
11
//将value对象以name名称绑定到会话
public void setAttribute(String name,Obejct value)

//获取name值,如果不存在返回null
public void getAttribute(String name)

//从会话中删除name属性,如果不存在不执行,不抛错
public void removeAttribute(String name)

//返回与会话有关的枚举值,没有则返回空枚举
public Enumeration getAttributeNames()

其他方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//使会话失效,同时删除属性对象
public void invalidate()

//检测当前可会是否为新会话
public Boolean isNew()

//返回会话创建时间
public long getCreationTime()

//返回在会话时间内Web容器接收到客户最后发出的请求的时间
public long getLastAccessedTime()

//返回在会话期间内客户请求的最长时间(秒)
public int getMaxInactiveInterval()

//允许客户请求的最长时间
public void setMaxInactiveInterval()

//返回当前会话的上下文环境,ServletContext对象可以使Servlet与Web容器进行通信
ServletContext getServletContext()

//返回会话期间的识别号,即sessionId
public String getId()

URL重写

URL重写是什么?

URL重写,是将URL重新写成Web应用可以处理的另一个URL的过程。

它只对链接起作用,只支持文本

它将一个或多个键值对添加到URL的查询字符串中,每个键值对key = value形式,如:

1
url?key_1=value_1&key_2=value_2...&key_n=value_n

URL和键值对之间用问好?分割,键值对之间用与符号&分割。

URL的内容会显示在浏览器的地址栏上,所以URL重写不适合用来传递敏感信息。

URL重写有什么用?

服务器在传递Session的ID属性时,是以Cookie的形式传递的。

在实际应用中,如果客户端不支持Cookie或禁用Cookie功能,那么服务器就无法获取Session的ID属性,也无法获取与该客户端对应的Session对象。

因此,URL重写技术被引入到Session机制中,在无法得知客户端是否支持Cookie时,将Session的ID属性追加到URL地址后面,从而实现会话跟踪功能。

例如:

http:localhost:8081/javaee/URLTest

经过URL重写后变为:

http:localhost:8081/javaee/URLTest;jsessionid=234A39C023E82EF

jessionid就是追加的Session ID属性

URL重写怎么用?

HttpServletResponse类提供了URL重写的方法:

1
2
3
public String encodeURL()

public String encodeRedirectURL()