Servlet_JSP最全学习资料教程

文章目录

  • Servlet
    • 1. Servlet运行流程:
    • 2. Servlet配置:
    • 3. doGet/doPost的区别与使用:
    • 4. Request
      • 1.概述
      • 2.常用方法
        • (1) 域方法:
        • (2) 获取请求头数据:
        • (3) 获取请求相关的其他方法
      • 3)常用方法总结:
      • 4.request获取请求参数
        • 获取请求参数的通用方式(Get/Post均可)
      • 5.实现转发:
      • 6.中文乱码问题
    • 5. Respone
      • 1. 响应正文
      • 2.设置响应头信息、状态码以及其他
        • (1) 设置响应头
        • (2) 设置状态码
        • (3) 其他
    • 6. 重定向
    • 7. 转发和重定向的区别与使用场景
        • 1) 区别
        • (2) 应用场景
    • 8.Cookie
      • 1) 为什么会有Cookie?
      • 2) 什么是Cookie
      • 3) 创建一个Cookie
      • 4)Cookie的存储:
      • 5) Cookie中获取Cookie
      • 6)Cookie的一些方法:
    • 9.**Session机制**
      • 1) 为什么有Session
      • 2) 什么是Session:
      • 3) 创建一个Session
      • 4) Session存储在哪里?
      • 5) Session存储数据:
      • 5) 获取Session
      • 6)Session的一些方法:
    • 10.Cookie Session小结
    • 11.ServletContext:
      • 1)简介:
      • 2)作用:
        • 2.1 域对象简介
        • 2.2 域对象方法
      • 3)获取ServletContext对象
  • JSP
    • 1. JSP简介
    • 2.JSP运行原理:
    • 3.在JSP中书写JAVA代码:
    • 4.JSP页面组成:
      • 指令标签
      • include 指令
      • JSP动作
    • JSP生命周期
    • JSP 评价

Servlet

img

1. Servlet运行流程:

  1. url:http://localhost:8080/Servlet_Test_login/loginServlet

    组成:服务器地址:端口号/虚拟项目名/servlet的别名

  2. uri:虚拟项目名/servlet别名

浏览器发送请求到服务器,服务器根据请求的URL地址中的URI信息在webapps目录下找到对应的项目文件,然后再web.xml中检索对应的servlet,找到后调用并执行servlet。

2. Servlet配置:

  1. 通过web.xml 配置

  2. 通过注解配置

    @WebServlet("/loginServlet")
    

loginServlet 即为此servlet的别名,通过

http://localhost:8080/Servlet_Test_login/loginServlet 即可访问。

3. doGet/doPost的区别与使用:

  1. 区别:

    在使用表单提交数据到服务器的时候有两张方式可共选择,一个是post一个是get。可在中的method属性中指定提交的方式。如:,如果不指定method属性,则会默认该属性为”get”方式。

    不同点一:

    通过get方式提交的数据有大小的限制,通常在1024字节左右。也就是说如果提交的数据很大,用get方法就可需要小心;而post方式没有数据大小的限制,理论上传送多少数据都可以。

    不同点二:

    通过get传递数据,实际上是将传递的数据按照”key,value”的方式跟在URL的后面来达到传送的目的的;而post传递数据是通过http请求的附件进行的,在URL中并没有明文显示。

    不同点三:

    通过Get方式提交的数据安全性不高,而Post方式的更加安全。

  2. 使用:

    h5:

    <body>
        <form action="/loginServlet" method="post">
            用户名:<input type="text" name="username"> <br>
            密码:<input type="password" name="password"><br>
            <input type="submit" value="登录">
        form>
    body>
    

    Servlet:

    @Override
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("UTF-8");
    		response.setCharacterEncoding("UTF-8");
    		//向服务器发送请求获取到参数
    		String username=request.getParameter("username");
    		String password=request.getParameter("password");
    		System.out.println(username+"--"+password);
    		
    
    		response.setHeader("Content-Type", "text/html; charset=UTF-8");
    		Writer out=response.getWriter();
    		out.write("用户名:"+username);
    		out.write("密码:"+password);
    		out.flush();
    		out.close();
    

4. Request

1.概述

request是Servlet.service()方法的一个参数,在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

2.常用方法

(1) 域方法:

  1. 存储
//用来存储一个对象,也可以称之为存储一个域属性
void setAttribute(String name, Object value)
    
Eg:servletContext.setAttribute(“xxx”, “XXX”)
//在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX
  1. 获取
//用来获取ServletContext中的数据
Object getAttribute(String name)
//获取名为xx的域属性
Eg:String value = (String)servletContext.getAttribute(“xxx”);

//获取所有域属性的名称;
Enumeration getAttributeNames()
  1. 移除
//用来移除ServletContext中的域属性
void removeAttribute(String name)

(2) 获取请求头数据:

//获取指定名称的请求头
String getHeader(String name)

//获取所有请求头名称
Enumeration getHeaderNames()
    
//获取值为int类型的请求头
int getIntHeader(String name)

(3) 获取请求相关的其他方法

//获取请求体的字节数,GET请求没有请求体,没有请求体返回-1;
int getContentLength()

/*	
	获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认
	为application/x-www-form-urlencoded,表示请求体内容使用了URL编码;
*/
String getContentType()

//返回请求方法,例如:GET/POST
String getMethod()

//返回当前客户端浏览器的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用;
Locale getLocale()
    
/*
	获取请求编码,如果没有setCharacterEncoding(),那么返回null,表示使用
	ISO-8859-1编码;
*/
String getCharacterEncoding()
    
/*
	设置请求编码,只对请求体有效!注意,对于GET而言,没有请求体!!!所以此方法
	只能对POST请求中的参数有效!
*/
void setCharacterEncoding(String code)

//返回上下文路径,例如:/Dmoe1
String getContextPath()
    
//返回请求URL中的参数,例如:username=zhangSan
String getQueryString()
    
//返回请求URI路径,例如:/Demo1/ServletDemo1
String getRequestURI()
    
/*
	返回请求URL路径,例如:http://localhost/Demo1/ServletDemo1即返回除了参数
	以外的路径信息;
*/
StringBuffer getRequestURL()
    
//返回Servlet路径,例如:/ServletDemo1
String getServletPath()
    
//返回当前客户端的IP地址
String getRemoteAddr()
    
//返回当前客户端的主机名,但这个方法的实现还是获取IP地址
String getRemoteHost()
    
//返回请求协议,例如:http
String getScheme()

//返回主机名,例如:localhost
String getServerName()
    
//返回服务器端口号,例如:8080
int getServerPort()

3)常用方法总结:

  1. 与Http请求相关:
    • getReader():返回一个缓冲读取器,用于读取请求正文中的文本。
    • getContentType() :返回请求正文的MIME类型,或者 null类型是否已知。
    • getContentLength() :返回请求正文的长度(以字节为单位),并由输入流提供,如果长度未知,则返回-1。
    • getCharacterEncoding() :返回此请求正文中使用的字符编码的名称。
    • setCharacterEncoding(java.lang.String env)设置此请求正文中使用的字符编码的名称。
    • setAttribute(String,Object):此方法将属性存储在请求上下文中; 这些属性将在请求之间重置。
    • getProtocol():以protocol / majorVersion.minorVersion格式返回请求使用的协议的名称和版本,例如HTTP / 1.1。
    • getScheme() :返回请求方式,例如 http,https或ftp。
  2. 请求客户端相关:
    • getServerPort(): 返回发送请求的端口号。
    • getRemoteAddr(): 返回发送请求的客户端或最后一个代理的Internet协议(IP)地址。
    • getRemoteHost() :返回客户端的完全限定名称或发送请求的最后一个代理。
    • getServerName(): 返回发送请求的服务器的主机名。
  3. 与request属性相关:
    • setAttribute(java.lang.String name, java.lang.Object o)在此请求中存储属性。 如果第二参数为null 那么相当于removeAttribute
    • getAttributeNames():Returns an Enumeration containing the names of the attributes available to this request.
    • removeAttribute(java.lang.String name):从此请求中删除属性。
    • getParameter(java.lang.String name):以String形式返回请求参数的值,如果参数不存在,则返回null。
    • getParameterMap():返回此请求的参数的java.util.Map。
    • getParameterValues(java.lang.String name):返回包含给定请求参数所具有的所有值的String对象数组,如果参数不存在,则返回null。

4.request获取请求参数

获取请求参数的通用方式(Get/Post均可)

//根据参数名称获取参数值
String getParameter(String name)

//根据参数名称获取参数值的数组 
String[] getParameterValues(String name)

//获取所有请求的参数名称
Enumeration<String> getParameterNames()

//获取所有参数的map集合
Map<String,String[]> getParameterMap()

通过表单提交数据:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/RequestDemo3" method="post">
   <table>
      <tr>
         <td>用户名</td>
         <td><input type="text" name="username"></td>
      </tr>
      <tr>
         <td>密码</td>
         <td><input type="password" name="password"></td>
      </tr>
      <tr>
         <td>性别</td>
         <td><input type="radio" name="gender" value="男"><td><input type="radio" name="gender" value="女"></td>
      </tr>
      <tr>
         <td>爱好</td>
         <td>
            <input type="checkbox" name="hobbies" value="游泳">游泳
            <input type="checkbox" name="hobbies" value="跑步">跑步
            <input type="checkbox" name="hobbies" value="网球">网球
      </tr>
      <input type="hidden" name="aaa" value="this is hidden text!">
      <tr>
         <td>从哪来的?</td>
         <td>
            <select name="address">    
               <option value="广州">广州</option>
               <option value="北京">北京</option>
               <option value="深圳">深圳</option>
            </select>
         </td>
      </tr>     
      <tr>
         <td>补充说明</td>
         <td>
            <textarea rows="2" cols="30" name="textarea"></textarea>
         </td>
      </tr>
      <tr>
         <td><input type="submit" value="提交"></td>
         <td><input type="reset" value="重置"></td>
      </tr>
   </table>
   </form>
</body>
</html>

在servlet 中接收:

@WebServlet("/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
     
    public RequestDemo3() {
     
        super();
    }

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
    //设置request字符编码的格式
    req.setCharacterEncoding("UTF-8");

    //通过html的name属性,获取到值
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String gender = req.getParameter("gender");

    //复选框和下拉框有多个值,获取到多个值
    String[] hobbies = req.getParameterValues("hobbies");
    String[] address = req.getParameterValues("address");

    //获取到文本域的值
    String description = req.getParameter("textarea");

    //得到隐藏域的值
    String hiddenValue = req.getParameter("aaa");

    System.out.println("username: " + username);
    System.out.println("password: " + password);
    System.out.println("gender: " + gender);
    System.out.println("hobbies: " + Arrays.toString(hobbies));
    System.out.println("address: " + Arrays.toString(address));
    System.out.println("description: " + description);
    System.out.println("hiddenValue: " + hiddenValue);
 }
}

5.实现转发:

服务器内部的资源跳转方式:

  1. Servlet跳转至html

    SuccessServlet

    //设置编码否则将会乱码:
    request.setCharacterEncoding("utf-8");
    
    //获取到requestDispatcher对象,跳转到successServlet.html
    RequestDispatcher requestDispatcher = request.getRequestDispatcher("/successServlet.html");
    
    //调用requestDispatcher对象的forward()实现转发,传入req和resp方法
    requestDispatcher.forward(request, response);
    
  2. Servlet内部的跳转:

    //存储数据
    req.setAttribute("user",user);
    //转发
    req.getRequestDispatcher("/successServlet").forward(req,resp);
    

我们可以同时使用ServletContext和request实现Servlet之间的通讯

一般来说我们尽量使用request,因为ServletContext代表着整个web应用,使用ServetContext会消耗大量的资源,而request对象会随着请求的结束而技术,资源会被回收,使用request域进行Servlet进行Servlet之间的通讯在开发中是非常频繁的

细节:

如果在调用foreard方法之前,在Servlet程序中写入的部分已经被真正地传到了客户端,forward方法将抛出IllegalStateException异常,也就是说,不要在在转发之前写数据给浏览器

如果调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到缓冲区中的内容将被清空,但是已写入到HttpServletResponse对象中的响应头字段信息保持有效

6.中文乱码问题

*//设置request字符编码的格式* 
request.setCharacterEncoding("UTF-8");

Tomcat服务器的默认编码是ISO 8859-1,而浏览器使用的是UTF-8编码。浏览器的中文数据提交给服务器,Tomacat以ISO 8859-1编码对中文编码,当我在Servlet读取数据的时候自然拿到乱码。所以设置request的编码为UTF-8,乱码就解决了

注意:按照上述例子中(使用post方式)乱码问题已经解决了,但是在get方式中尝试仍然是乱码。在此我们需要了解post方法是怎么进行参数传递的。

当我们点击提交按钮的时候,数据封装进了Form Data中,http请求中把实体主体带过去了【传输的数据称之为主体】,既然request对象封装了http请求,所以request对象可以解析到发送过来的数据,于是只要把编码设置成UTF-8就可以解决乱码问题而get方式不同,它的数据是从消息行带过去的,没有封装到request中,所以使用request设置编码是无效的。

解决方法: 我们既然知道Tomcat默认的编码是ISO 8859-1,那么get方式由消息体带过去给浏览器的时候肯定是用ISO 8859-1编码了。

5. Respone

1. 响应正文

response作为响应对象,他提供了两个响应流对象,可以向客户端输出响应正文

//获取字符流
l PrintWriter out = response.getWriter()

//获取字节流
l ServletOutputStream out = response.getOutputStream()
ServletOutputStream servletOutputStream = resp.getOutputStream();

servletOutputStream.write("你好世界".getBytes());

servletOutputStream.write("Just for test".getBytes());

如果Tomcat版本在8以下 在outputStream中使用print()方法接收字符串,由于编码的问题,输出中文字符串的时候,就会出现乱码问题

原因是,outputStream是输出二进制的数据,print()方法先有一个将字符串转为二进制的过程,Tomcat会使用IOS 8859-1编码转换,所以出现了问题

但是使用write()却可以很好的解决这个问题,这是因为,write(“Just for test”.getBytes());转换为byte[]数组的时候默认使用的是gb2312编码,所以不会出现问题

建议写法:

//设置编码
response.setContentType("text/html;charset=utf-8");
//输出
response.getWriter().write("登录失败,用户名或密码错误");

好处:不只会调用response.setCharaceterEncoding(“utf-8”),还会设置content-type响应头(客户端浏览器会使用content-type头来解读响应数据)

总结:响应正文内容为字符,那么使用respone.getWriter(),如果响应内容是字节,例如下载文件,可以使用 response.getOutputStream()

注意:在同一个请求中,不能同时使用这两个流,否则会抛出 IllegalStateException 异常。

getWriter() 的缓冲区问题

它的类型是PrintWriter类型的,所以它有缓冲区,缓冲区的默认大小为8KB,在限定代销范围以内,数据先存放在缓冲区,等到超过范围后,服务器刷新流,缓冲区中的数据发送倒客户端,如果想要响应数据马上发送到客户端,可以调用response.flushBuffer()方法来手动刷新缓冲区

2.设置响应头信息、状态码以及其他

(1) 设置响应头

使用 response 对象的 setHeader() 方法来设置响应头

//设置content-type响应头,告诉浏览器响应内容为html类型,编码为utf-8。而且同时会设置response的字符流编码为utf-8,即response.setCharaceterEncoding(“uaav tf-8”);
response.setHeader(“content-type”, “text/html;charset=utf-8);

//5秒后自动跳转到指定主页
response.setHeader("Refresh","5; URL=http://www.xxx.com");

(2) 设置状态码

//设置状态码* 
response.setStatus(200) ;
//当发送错误状态码时,跳转到指定错误页面,但可以显示错误信息
response.sendError(404, “您要查找的资源不存在”);

(3) 其他

//等同于response.setHeader(“content-type”, “text/html;charset=utf-8”)
response.setContentType("text/html;charset=utf-8")

//设置字符响应流的字符编码为UTF-8    
response.setCharacterEncoding(“utf-8)
    
//下例表示定时刷新,3秒后跳转页面
response.setHeader("Refresh", "3;URL=Bservlet");

3.常用方法总结:

  1. 数据写入有关:
    • setBufferSize(size): 设置响应正文的首选缓冲区大小。
    • flushBuffer(): 强制将缓冲区中的任何内容写入客户端。
    • getBufferSize(): 返回用于响应的实际缓冲区大小。
    • getOutputStream(): 返回ServletOutputStream适合在响应中写入二进制数据。
    • getWriter(): 返回PrintWriter可以将字符文本发送到客户端的对象。
    • resetBuffer(): 清除响应中底层缓冲区的内容,而不清除标头或状态代码。
  2. http相应有关:
    • setCharacterEncoding(charset): 设置发送到客户端的响应的字符编码(MIME字符集),例如,设置为UTF-8。
    • getCharacterEncoding(): 返回用于此响应中发送的正文的字符编码(MIME字符集)的名称。
    • getContentType(): 返回用于此响应中发送的MIME正文的内容类型。
    • getLocale(): 使用该setLocale(java.util.Locale)方法返回为此响应指定的语言环境。
    • isCommitted(): 返回一个布尔值,指示响应是否已提交。
    • reset(): 清除缓冲区中存在的所有数据以及状态代码和标头。
    • setContentLength(len): 设置响应中内容主体的长度在HTTP-servlet中,此方法设置HTTP-Content-Length标头。
    • setContentType(java.lang.String): 如果尚未提交响应,则设置发送到客户端的响应的内容类型。
    • setLocale(java.util.Locale): 如果尚未提交响应,则设置响应的区域设置。

6. 重定向

当你访问 www.xxx.com的时候,页面被跳转到了另一个页面,并且浏览器地址栏中的URL也发生了变化,这种技术就叫做重定向

完成重定向有两个关键的地方

设置响应码
设置Location头
响应码200的意思是响应成功,而重定向对应的响应码为302,所以我们需要设置响应码

因为重定向的原理为,发出二次请求,所以你需要给浏览器指定第二次请求的URL,所以需要蛇者Location头

注意:同服务器下可以使用相对路径

response.setStatus(302);

response.setHeader("Location", "www.xxx.com");

简单的写法

response.sendRedirect("www.xxx.com");

7. 转发和重定向的区别与使用场景

1) 区别

(一) 实际发生未知不同,地址栏不同

A:转发是发生在服务器的

B:转发是由服务器进行跳转的,转发时,浏览器的地址栏是没有发生变化的,(访 问了Servlet1后即使页面跳转到了Servlet2,但浏览器的地址还是Servlet1的) 也就是说浏览器是不知道该跳转的动作,实现转发只是一次的http请求,一次转 发中request和response对象都是同一个,这也解释了为什么可以使用request 作为域对象进行Servlet之间的通讯

C:重定向是发生在浏览器的

D:重定向是由浏览器进行跳转的,进行重定向跳转的时候,浏览器的地址会发生变化,实现重定向的原理是由response的状态码和location头组合而实现的,这 是由浏览器进行的页面跳转实现会发出两个http请求,request域对象是无效的, 因为它不是同一个request对象

(二) 用法不同

原则:

  1. 给服务器用的直接从资源名开始写,

  2. 给浏览器用的要把应用名协写上

  3. Requst.getRequestDispatcher(“/资源名 URL”).forward(request,response);

​ 转发时“/”代表的是本应用程序的根目录(web-01)

  1. Response.send(“/web应用/资源名URL”);

    重定向时“/”代表的是webapps目录

(三) 能够去往的URL的范围不同

转发是服务器跳转,只能去往当前web应用的资源

重定向是服务器跳转,可以去往任何的资源

(四) 传递数据的类型不同

转发的request对象可以传递各种类型的数据,包括对象

重定向只能传递字符串

(五) 跳转的时间不同

转发时:执行到跳转语句就会立刻跳转

重定向:整个页面执行完后才会执行跳转

(2) 应用场景

总结:转发是带着转发前的请求的参数。重定向时新的请求

典型的应用场景:

1:转发:访问Servlet处理业务逻辑,然后转发到jsp中去处理结果,浏览器里URL不变

2:重定向:提交表单,处理成功后重定向到另一个jsp,防止表单重复提交,浏览器里的URL变了

8.Cookie

1) 为什么会有Cookie?

Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。

你可能会有这样的经历,登陆一个网站的时候会提醒你要不要记住账户和密码,这样下次来你就不用再次输入账号密码了。这就是cookie的作用,当我们再次访问的时候,方便服务器直接根据我们的cookie来直接取上一次取过的东西(对于每一个cookie服务器会对这个cookie存储上一次我们拿过的数据,下一次对于同一个cookie的时候,就直接在这里取)

2) 什么是Cookie

Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),(服务器告诉浏览器设置一下cookie),浏览器自动会将Cookiekey/value保存到某个目录下的文本文件内,下次请求同一网站时也会自动发送该Cookie给服务器,即添加在请求头部(前提是浏览器设置为启用cookie)。
Cookie就是一个小型文件(浏览器对cookie的内存大小是有限制的-------用来记录一些信息)

3) 创建一个Cookie

如果不设置Cookie的 MaxAge 最大存储时间 那么默认会存储在浏览器运行内存之中 浏览器关闭之后 Cookie 信息消失。

构造函数 :

Cookie(java.lang.String name, java.lang.String value)

构造具有指定名称和值的cookie。

  Cookie userName = new Cookie("UserName",UserID);
  Cookie userPassword = new Cookie("UserPassword",UserPwd);

  response.addCookie(userName);
  response.addCookie(userPassword);
  • setMaxAge(int expiry):以秒为单位设置cookie的最大年龄。 返回值: void

  • setPath(java.lang.String uri):指定客户端应返回cookie的cookie的路径 返回值: void

  • setComment(java.lang.String purpose):指定描述cookie用途的注释。返回值: void

  • setValue(java.lang.String newValue):创建cookie后,为cookie分配新值。 返回值: void

    注:以上四个方法都有对应的get方法 返回类型为设置的类型。

如果设置了存储时间那么cookie信息就存储在浏览器文件中也就是说硬盘上面 如果不设置有效路径那么每一次对服务器的请求都会带着cookie信息 而且由于会明文保存在
http协议中所以推荐对存储的cookie信息进行加密存储。

 userName.setMaxAge(60*60*24); //保存一天
 userPassword.setMaxAge(60*60*24); //保存一天

 userName.setPath("/Login.jsp"); //只有在请求/login.jsp 的时候才把cookie信息 加到http请求中

4)Cookie的存储:

Cookie 存储在HTTP 请求中 的Cookie 字段中 且你存什么它保存什么 本身并不加密存储。

Request URL: http://localhost:8089/index.jsp
Request Method: GET
Status Code: 200 
Remote Address: [::1]:8089
Referrer Policy: no-referrer-when-downgrade
Content-Length: 145
Content-Type: text/html;charset=UTF-8
Date: Mon, 26 Nov 2018 00:29:15 GMT
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Cookie: UserPassword=123123;JSESSIONID=B6348CE35C47ED815CC1738C9E315A59;UserName=ad123123
Host: localhost:8089
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/69.0.3497.100 Safari/537.36

5) Cookie中获取Cookie

小心一种特殊情况 就是用户注销了自己的信息 从数据库中删除了自己的信息 但是自己的cookie并没有被删除的问题

 int islogin = 0;
 for (Cookie ck : request.getCookies()) {
     
     if(ck.getName().equals("UserName")){
      //不要用 == 去判断
         response.getWriter().println("已经登录成功");
         islogin ++;
     }
 }

 if(islogin == 0){
     
     response.getWriter().println("点击登录");
 }

6)Cookie的一些方法:

  • setMaxAge(int expiry):以秒为单位设置cookie的最大年龄。 设置Cookie 过期时间
  • setValue(java.lang.String newValue):创建cookie后,为cookie分配新值。
  • setDomain(java.lang.String pattern):指定应在其中显示此cookie的域。
  • setComment(java.lang.String purpose):指定描述cookie用途的注释。
  • setPath(java.lang.String uri):指定客户端应返回cookie的cookie的路径。
  • setSecure(boolean flag):向浏览器指示是否应仅使用安全协议(例如HTTPS或SSL)发送cookie。 设置Cookie Http-Only
  • setVersion(int v):设置此cookie符合的cookie协议的版本。

9.Session机制

1) 为什么有Session

除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。

2) 什么是Session:

Session是另一种记录客户状态的机制,不同的是 Cookie保存在客户端浏览器中,而Session保存在服务器上 。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的"通行证"来确定客户身份的话,那么Session机制就是通过检查服务器上的"客户明细表"来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

Session对应的类为javax.servlet.http.HttpSession类。每个来访者对应一个Session对象,所有该客户的状态信息都保存在这个Session对象里。Session对象是在客户端第一次请求服务器的时候创建的。Session也是一种key-value的属性对,通过getAttribute(String key)和setAttribute(String key,Object value)方法读写客户状态信息。Servlet里通过request.getSession()方法获取该客户的Session

3) 创建一个Session

HttpSession session = request.getSession(); //如果服务器已经创建那么返回session 否则新建一个session 并返回

response.getWriter().println(session.getId());
  • HttpSession getSession():返回与此请求关联的当前会话,或者如果请求没有会话,则创建一个会话。
  • HttpSession getSession(boolean create):返回HttpSession 与此请求关联的当前值,如果没有当前会话且create为true,则返回新会话。
  • int getMaxInactiveInterval():返回servlet容器在客户端访问之间保持此会话打开的最长时间间隔(以秒为单位)
  • int setMaxInactiveInterval(int interval):指定servlet容器使此会话失效之前的客户端请求之间的时间(以秒为单位)

Session 本质是由客户第一次访问服务器由服务器自己创建的

4) Session存储在哪里?

  • Seeion ID的唯一性如何保证的:当用户第一次访问服务器的时候,服务器会创建一个Session对象给用户,并且产生一个唯一标识ID 存在Session 对象中 并且将此唯一Session ID 发送到浏览器保存在浏览器中 [存储在浏览器的Cookie中 名称为:JSESSIONID], 作为用户的唯一标识 也就是说 唯一标识Session的ID 会存储一份在客户浏览器中,Session 对象存储在服务器中。

  • 本质上唯一标识只存储在浏览器运行内存中 也就是说关闭浏览器就会失效。

  • Session 默认生效时间 30分钟。

  • 如果session 失效了 那么他又会生成一个session 并发送一个sessionID 给浏览器存储。

  • 规则:如果Session 在规定的时间内没有使用就销毁 否则就重新计时。

 session.invalidate();
Request URL: http://localhost:8089/login
Request Method: POST
Status Code: 200 
Remote Address: [::1]:8089
Referrer Policy: no-referrer-when-downgrade
Content-Length: 57
Content-Type: text/html;charset=UTF-8
Date: Mon, 26 Nov 2018 01:11:19 GMT
Set-Cookie: UserName=3444444444444444
Set-Cookie: UserPassword=23423424
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 40
Content-Type: application/x-www-form-urlencoded
Cookie: Webstorm-66e715af=5d7e1fa0-a9e9-4c01-9c16-aaff75cf10f7; JSESSIONID=2AF4A84C2F8FC452F54C77D3092B2E1B; 
UserName=3444444444444444; UserPassword=23423424
Host: localhost:8089
Origin: http://localhost:8089
Referer: http://localhost:8089/Login.jsp
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/69.0.3497.100 Safari/537.36

5) Session存储数据:

通过如下访问 获取或者存储Session数据 当然你要保证你这次的Session 是你上次存储的Session

  • void setAttribute(java.lang.String name, java.lang.Object value) :使用指定的名称将对象绑定到此会话。
  • java.lang.Object getAttribute(java.lang.String name) :返回在此会话中使用指定名称绑定的对象,或者 null如果名称下没有绑定任何对象。

最好用一个属性存储一个值表示 此时是否具有 有效Session 例如

  session.setAttribute("isLoginStore",true);
  session.setAttribute("id",userName);
  session.setAttribute("pwd",userPassword);

  //获取
  if(getAttribute(isLoginStore) != null){
     
     session.getAttribute("id");
     session.getAttribute("pwd");
  }else{
     
     response.getWriter().println("登录超时!请重新登录");
  }

5) 获取Session

HttpSession session = request.getSession();

另外维持一个会话的核心就是客户端的唯一标识,即 session id

6)Session的一些方法:

  • Object getAttribute(java.lang.String name):返回在此会话中使用指定名称绑定的对象,或者 null如果名称下没有绑定任何对象。
  • Enumeration getAttributeNames():返回Enumeration的String含有与本次会议的所有对象的名称的对象。
  • long getCreationTime():返回创建此会话的时间,以格林威治标准时间1970年1月1日午夜以来的毫秒数为单位。
  • String getId():返回包含分配给此会话的唯一标识符的字符串。
  • long getLastAccessedTime():返回客户端最后一次发送与此会话关联的请求 并以容器收到请求的时间为标记。
  • getServletContext():返回此会话所属的ServletContext。
  • invalidate():使此会话无效,然后取消绑定绑定到它的任何对象。
  • isNew() :返回true如果客户端还不知道该会话或者如果客户选择不参加会议。
  • setMaxInactiveInterval(int interval)指定servlet容器使此会话失效之前的客户端请求之间的时间(以秒为单位)。
  • removeAttribute(java.lang.String name):从此会话中删除与指定名称绑定的对象。
  • setAttribute(java.lang.String name, java.lang.Object value)使用指定的名称将对象绑定到此会话。

10.Cookie Session小结

首先 session 是一个抽象概念,开发者为了实现中断和继续等操作,将 user agent 和 server 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是 session 的概念。

而 cookie 是一个实际存在的东西,http 协议中定义在 header 中的字段。可以 认为是 session 的一种后端无状态实现。

1,session 在服务器端,cookie 在客户端(浏览器)。

2,session 默认被存在在服务器的一个文件里(不是内存)。

3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)。
4,session 可以放在 文件、数据库、或内存中都可以。

免登录使用Cookie

用户验证这种场合一般会用 session

11.ServletContext:

1)简介:

ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

实现Application的职责 完成所有用户共享数据 使得不同用户可以共享同一个对象 Servlet为我们实现了ServletContent对象来完成这个功能 官方文档

  • 由服务器创建
  • 所有用户共享
  • 一个项目只有一个
  • 生命周期:从你将项目部署到服务器到 服务器停止此网站或项目被停止

2)作用:

  1. servletContext是一个域对象。

  2. 可以读取全局配置参数。获取项目中web.xml文件的全局配置信息。

    web-app下:

    
        Author
        JxKicker
    
    
        age
        18
    
    

    获取配置信息:

    ServletContext sc = this.getServletConfig().getServletContext();
    String val = sc.getInitParameter("Author");
    String key[] = sc.getInitParameters(); //返回所有自定义配置项
    response.getWriter().println("作者:" + val );
    
  3. 获取项目 webroot下的文件资源的绝对路径。

    ServletContext sc = this.getServletConfig().getServletContext();
    String realPath = sc.getRealPath("/resources/my.txt");
    response.getWriter().println(realPath);
    
  4. 获取项目 webroot下的文件资源的流对象 但是不能获取类文件的流对象。

    InputStream stream_  = sc.getResourceAsStream("/resources/my.txt");
    
  5. 可以用来统计网站访问情况。

2.1 域对象简介

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

2.2 域对象方法

凡是域对象都有如下3个方法:

  • 往域对象里面添加数据,添加时以key-value形式添加。

    setAttribute(name,value);
    

    name是String类型,value是Object类型;

  • 根据指定的key读取域对象里面的数据。

    getAttribute(name);
    
  • 根据指定的key从域对象里面删除数据。

    removeAttribute(name);
    

3)获取ServletContext对象

​ 在Servlet对象中可以直接使用this:

ServletContext sc = this.getServletContext();

​ 在jsp中:

ServletContext sc = this.getServletConfig().getServletContext();

​ 通过request获取:

ServletContext context = req.getSession().getServletContext();

4)数据存储交互:

  • void removeAttribute(java.lang.String name):

    从servlet上下文中删除具有给定名称的属性。

  • void setAttribute(java.lang.String name, java.lang.Object object):

    将对象绑定到此servlet上下文中的给定属性名称。

  • java.lang.Object getAttribute(java.lang.String name) :

    返回具有给定名称的servlet容器属性,或者null如果该名称没有属性。

  • java.util.Enumeration getAttributeNames():

    返回Enumeration包含此servlet上下文中可用的属性名称的内容。

5)其他方法:

01 Object getAttribute(String name) 返回给定名的属性值

02 Enumeration getAttributeNames() 返回所有可用属性名的枚举
03 void setAttribute(String name,Object obj) 设定属性的属性值
04 void removeAttribute(String name) 删除一属性及其属性值
05 String getServerInfo() 返回JSP(Servlet)引擎名及版本号
06 String getRealPath(String path) 返回一虚拟路径的真实路径
07 ServletContext getContext(String uripath) 返回指定WebApplication的application对象
08 int getMajorVersion() 返回服务器支持的Servlet API的最大版本号
09 int getMinorVersion() 返回服务器支持的Servlet API的最大版本号
10 String getMimeType(String file) 返回指定文件的MIME类型
11 URL getResource(String path) 返回指定资源(文件及目录)的URL路径
12 InputStream getResourceAsStream(String path) 返回指定资源的输入流
13 RequestDispatcher getRequestDispatcher(String uripath) 返回指定资源的RequestDispatcher对象
14 Servlet getServlet(String name) 返回指定名的Servlet
15 Enumeration getServlets() 返回所有Servlet的枚举
16 Enumeration getServletNames() 返回所有Servlet名的枚举
17 void log(String msg) 把指定消息写入Servlet的日志文件
18 void log(Exception exception,String msg) 把指定异常的栈轨迹及错误消息写入Servlet日志文件
19 void log(String msg,Throwable throwable) 把栈轨迹及Throwable异常信息写入Servlet日志文件

JSP

1. JSP简介

  • JSP全称: Java Server Page,它是用于展示信息操作。
  • 为了servlet展示信息的不方便,引入了JSP。
  • JSP本质上也是一个servlet。
  • JSP就是在HTML页面中嵌入了java代码。

2.JSP运行原理:

在Tomcat中的web.xml中,有一个默认的servlet,处理不可以处理的请求,还有一个JSPservlet,又叫servlet引擎,所有后缀为.jsp的文件都处理。

当浏览器访问http://localhost:8080/day9_1/index.jsp。服务器发现后缀为.jsp,它会根据路径找到index.jsp文件,会将index.jsp翻译成index_jsp.java文件,对这个java文件进行编译,产生一个index_jsp.class文件,将class文件加载运行。将JSP翻译成java文件,它是将JSP中的所有的HTML代码通过流进行输出,也就是说最终翻译成class,被虚拟机加载,它本质是servlet,它就会往回响应,响应回去就是把JSP中的HTML代码以流的方式写回浏览器。所以在JSP中展示出了HTML代码。

3.在JSP中书写JAVA代码:

标签 语法 作用
声明标签 <%! 变量或方法声明%> 声明JSP内所使用的全局变量或方法或内部类(它用于定义成员)(写的内容在成员位置上)
表达式 <%= 表达式 %> 输出java中变量或者表达式的值到页面上(它用于输出) out.print(内容)
程序代码标签 <%程序代码%> 编写java程序代码,但不可以定义代码(它用于定义局部)(声明的变量在局部位置_jspService方法中)

4.JSP页面组成:

一个JSP页面可以被分为以下几部份:

  • 静态数据,如HTML
  • JSP指令,如include指令:JSP指令控制JSP编译器如何去生成servlet,以下是可用的指令
  • JSP脚本元素和变量
  • JSP动作
  • 用户自定义标签

指令标签

页面指令page –页面指令有以下几个选项: language指令 很少用,默认为java 虽然一开始都在说jsp可能能支持其他语言例如C# php 但是一直到jsp死掉了 都没有实现过。

  • import:使一个JAVA导入声明被插入到最终页面文件。导入Java包
 <%@ page import="java.util.*" %>
  • contentType:规定了生成内容的类型。当生成非HTML内容或者当前字符集character set并非默认字符集时使用。指定客户端读码方式
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  • errorPage:处理HTTP请求时,如果出现异常则显示该错误提示信息页面。
  <%@ page  errorPage="Error.jsp" %>
  • isErrorPage:如果设置为TRUE,则表示当前文件是一个错误提示页面。
  <%@ page isErrorPage="true" %>
  • isThreadSafe:表示最终生成的servlet是否安全线程(threadsafe)。
  <%@ page isErrorPage="true" isThreadSafe="true" %>
  • pageEncoding:指定文件编码,设定的是服务端以那种编码格式读取jsp文件
 <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
  • extend:指定这个jsp文件继承自什么类,默认不使用 乱用有麻烦。

include 指令

将另一个jsp文件包含进来,但是这个包含是静态包含

  <%@include file="index.jsp" %>

JSP动作

JSP动作:JSP动作是一系列可以调用内建于网络服务器中的功能的XML标签。JSP提供了以下动作:

  • jsp:include 和子过程类似,JAVA SERVLET暂时接管对其它指定的JSP页的请求和响应。当处理完该JSP页后就马上把控制权交还当前JSP页。这样JSP代码就可以在多个JSP页中共享而不用复制。
  • jsp:param 可以在jsp:include, jsp:forward或jsp:params块之间使用。指定一个将加入请求的当前参数组中的参数。
  • jsp:forward 用于处理对另一个JSP或SERVLET的请求和响应。控制权永远不会交还给当前JSP页。
  • jsp:plugin Netscape Navigator的老版本和Internet Explorer使用不同的标签以嵌入一个applet。这个动作产生为嵌入一个APPLET所需要的指定浏览器标签。
  • jsp:fallback 如果浏览器不支持APPLETS则会显示的内容。
  • jsp:getProperty 从指定的JavaBean中获取一个属性值。
  • jsp:setProperty 在指定的JavaBean中设置一个属性值。
  • jsp:useBean 创建或者复用一个JavaBean变量到JSP页。`

JSP生命周期

JSP执行过程

  • JSP生命周期被定义为从创建到破坏的过程。这类似于一个Servlet生命周期,需要一个额外的步骤来将JSP编译成Servlet。JSP执行过程以下是JSP遵循的过程
  • 编译: 解析JSP。将JSP转换为servlet。编译servlet。
  • 初始化: 当容器加载JSP时,它会在处理任何请求之前调用jspInit()方法 ,一般会在jspInit()方法中初始化数据库连接,打开文件和创建查找表。
  • 执行: JSP引擎将调用JSP中的_jspService()方法 响应请求
  • 清理: jspDestroy()方法,如:释放数据库连接或关闭打开的文件。

JSP 评价

是一个在当下已经落后的技术,学习的必要性在于许多框架和在运行项目任然在运行它,但是后续慢慢消失逐渐被新的框架取代是必然趋势,就像ASP.NET 事件驱动动态web一样都会逐渐消失

你可能感兴趣的:(Java,java,servlet,session,jsp,cookie)