一.Servlet(三)
1.数据响应
getWriter()获取字符流(只能响应回字符);
getOutputStream()获取字节流(能响应一切数据)。
响应回的数据到客户端被浏览器解析。
注意:两者不能同时使用。
java.lang.IllegalStateException: getWriter() has already been called for this response
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet02...");
// 设置响应类型 默认是纯文本
response.setContentType("text/html");
// 得到输出流 字符输出流
/*PrintWriter writer = response.getWriter();
writer.write("Hello");
writer.write("<h3>Hello</h3>");
writer.close();*/
// 得到字节输出流
ServletOutputStream out = response.getOutputStream();
out.write("Hello".getBytes());
out.write("<h3>Hello</h3>".getBytes());
out.close();
}
}
package com.shsxt.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet03 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet03...");
// 设置响应类型 默认是纯文本
/*response.setContentType("application/json");
String json = "{\"uanme\":\"zhangsan\",\"upwd\":\"123\"}";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(json);
writer.close();*/
response.setContentType("text/html");
String form = "<form action='ser02' method='get'> userName: <input type='text' name='uname' /> <br/> userPwd: <input type='password' name='upwd' /> <br/> <input type='submit' value='Login' /> </form>";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(form);
writer.close();
}
}
2.响应乱码
乱码原因:在响应时,服务器经过网络传输响应数据到客户端,服务器默认编码为ISO-8859-1,该编码不支持
中文;客户端也有其默认编码。
总结:①服务端和客户端编码不一致;②客户端和服务端的编码不支持中文。
如何解决:①设置客户端和服务端的编码一致;②客户端和服务端编码都支持中文;
getWriter()乱码:
响应中文必定出乱码,由于服务器端在进行编码时默认会使用 ISO-8859-1 格式的编码,该编码方式并不支持中文。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet04 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet04...");
// 设置服务端的编码
//response.setCharacterEncoding("UTF-8");
// 设置客户端的编码
//response.setHeader("content-type", "text/html;charset=UTF-8");
// 同时设置客户端和服务端的编码
response.setContentType("text/html;charset=UTF-8");
/*String str = "<h3>你好</h3>";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(str);
writer.close();*/
String str2 = "<h2>你好</h2>";
// 得到字节输出流
ServletOutputStream out = response.getOutputStream();
out.write(str2.getBytes());
out.close();
}
}
3. 响应图片
①得到图片存放的路径
②通过路径得到文件对象
③得到字节输出流
④得到文件对象的输入流
⑤循环读取,并写出到浏览器
package com.shsxt.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet05 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("响应图片...");
// 设置响应类型
response.setContentType("image/jpeg");
// 1、得到图片存放的路径
String realPath = request.getServletContext().getRealPath("/WEB-INF/jay.jpg"); // 得到项目在服务器中存放的真实路径
// 得到图片
// String file = realPath + "/WEB-INF/jay.jpg";
System.out.println(realPath);
// 2、通过路径得到文件对象
File file = new File(realPath);
// 3、得到字节输出流
ServletOutputStream out = response.getOutputStream();
// 4、得到文件对象的输入流
InputStream in = new FileInputStream(file);
// 5、循环读取,并写出到浏览器
byte[] bytes = new byte[1024];
int len = 0;
while((len = in.read(bytes)) != -1) {
// 写出
out.write(bytes,0,len);
}
out.flush();
in.close();
out.close();
}
}
4.重定向
1)重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务器接收,经过处理服务器进行响应,与
此同时,服务器给客户端一个地址(下次请求的地址 resp.sendRedirect("url");),当客户端接收到响应后,立刻、马上、
自动根据服务器 给的地址进行请求的发送第二个请求,服务器接收请求并作出 响应,重定向完成。从描述中可以看出重
定向当中有两个请求存在,并且属于客户端行为。
2)请求转发和重定向的区别
①请求转发是服务端跳转,重定向是客户端跳转
②请求转发只有一次请求,重定向有两次请求
③请求转发地址栏不发生改变,重定向地址栏会改变
④请求转发request域对象能共享,重定向不能共享
⑤请求转发只能请求当前资源下的路径,重定向可以任意地址
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet06 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("重定向...");
// 请求转发
// request.getRequestDispatcher("index.html").forward(request, response);
// 重定向
//response.sendRedirect("index.html");
/*设置request域对象*/
//request.setAttribute("name", "zhangsan");
// 请求转发
//request.getRequestDispatcher("ser07").forward(request, response);
// 重定向
//response.sendRedirect("ser07");
/* 请求地址 */
//request.getRequestDispatcher("/sr02/ser01").forward(request, response);
//response.sendRedirect("/sr02/ser01");
//request.getRequestDispatcher("http://www.baidu.com").forward(request, response);
response.sendRedirect("http://www.baidu.com");
}
}
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet07 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet07...");
// 获取域对象中的值
String name = (String) request.getAttribute("name");
System.out.println("name:" + name);
}
}
5.请求时的路径问题
http://loaclhost:8080/s01/ser01
注:ser01和ser02s是两个同级的servlet
1)相对路径
相对于当前资源所在路径 ser02(重定向) ser02(请求转发)
2)绝对路径
完整路径
①以http://开头的路径,已经跨域,可以访问任意地址 http://loaclhsot:8080/s01/ser02 重定向)(请求转发不可以)
② 以/开头,定位在端口之后 /s01/ser02(重定向) /ser02(在请求转发时,"/"代表的含义是从http开始到站点名后)
3)请求转发:
带"/"的绝对路径,定位的位置是在站点名之后
4)重定向:
带"/"的绝对路径,定位的位置是在端口之后
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet08 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet08...");
// "/"代表的是http://localhost:8080/sr03/
// 相对路径:http://localhost:8080/sr03/
//request.getRequestDispatcher("index.html").forward(request, response); // OK
//request.getRequestDispatcher("/index.html").forward(request, response); // OK
//request.getRequestDispatcher("sr03/index.html").forward(request, response); // 404
//request.getRequestDispatcher("/sr03/index.html").forward(request, response); // 404
//request.getRequestDispatcher("htpp://localhost:8080/sr03/index.html").forward(request, response); // 404
// "/"代表的是http://localhost:8080/
// 相对路径:http://localhost:8080/sr03/
//response.sendRedirect("index.html"); // OK
//response.sendRedirect("/index.html"); // 404
//response.sendRedirect("sr03/index.html"); // 404
//response.sendRedirect("/sr03/index.html"); // OK
//response.sendRedirect("htpp://localhost:8080/sr03/index.html");
}
}
二.Cookie的创建和发送
1.Service方法会自动区分GET请求或Post请求
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Cookie的创建和发送
*/
public class Cookie01 extends HttpServlet {
private static final long serialVersionUID = 1L;
public Cookie01() {
super();
}
/**
* Service方法会自动区分GET请求或Post请求
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie对象
Cookie cookie = new Cookie("uname","admin");
// 创建Cookie对象
Cookie cookie2 = new Cookie("uname2","zhangsan");
// 发送Cookie对象(响应cookie)
resp.addCookie(cookie);
resp.addCookie(cookie2);
}
/**
* GET请求
*/
/*protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}*/
/**
* POST请求
*/
/*protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}*/
}
2.获取 Cookie对象
提供了一个 getCookies()的方法用来获取客户端回传的所有cookie 组成的一个数组,
如果需要获取单个 cookie 则需要通过遍历,getName()获取 Cookie 的名称,getValue()获取 Cookie 的值。
package com.shsxt.servlet;
import java.io.IOException;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Cookie02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取cookie数组
Cookie[] cookies = request.getCookies();
// 判断cookie数组是否为空
if (cookies != null && cookies.length > 0) {
// 遍历Cookie数组
for (Cookie cookie : cookies) {
// 得到cookie的名称和值
String name = cookie.getName();
String value = cookie.getValue();
// 获取时通过 URLDecoder.decode()来进行解码
name = URLDecoder.decode(name);
value = URLDecoder.decode(value);
System.out.println("名称:" + name + ",值:" + value);
// 得到指定名称的value
if ("uname".equals(name)) {
System.out.println(value);
}
}
}
}
}
3.Cookie到期时间的设定
到期时间,到期时间用来指定该 cookie 何时失效。默认为当前浏览器关闭即失效。
可以手动设定 cookie 的有效时间(通过到期时间计算),通过 setMaxAge(int time);方法设定 cookie 的最大有效
时间,以秒为单位。
大于 0 的整数,表示存储的秒数;
若为负数,则表示不存储该 cookie;
若为 0,则删 除该 cookie。
负整数:cookie 的 maxAge 属性的默认值就是-1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那么 cookie
就会消失。
正整数:表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算关闭浏
览器,就算重启客户端电脑,cookie 也会存活相应的时间。
零:cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 Cookie 的setMaxAge(0)来删除这个 Cookie。 无论是在浏览器内存中,还是在客户端硬盘上都会
删除这个 Cookie
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Cookie03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建Cookie对象
Cookie cookie = new Cookie("upwd","123456");
// 设置cookie到期时间
// 1、 默认值,只在当前浏览器中存活,关闭浏览器即失效
// cookie.setMaxAge(-1);
// 2、存活指定时间,单位是秒
// cookie.setMaxAge(20); // 存活15秒
// 3、设置为0,表示即刻删除
cookie.setMaxAge(0);
// 响应cookie
response.addCookie(cookie);
Cookie cookie2 = new Cookie("upwd2","1234567");
response.addCookie(cookie2);
// 删除指定cookie对象
Cookie cookie3 = new Cookie("uname",null);
// 删除cookie
cookie3.setMaxAge(0);
// 响应cookie
response.addCookie(cookie3);
}
}
4.Cookie的注意
①Cookie存在本机上,换电脑后失效;Cookie不跨浏览器
②出现同名Cookie,会覆盖
③不同的浏览器对 Cookie 也有限定,Cookie 的存储有是上限的。
④Cookie不能存中文
Cookie 中不能出现中文,如果有中文则通过 URLEncoder.encode()来进行编码,获取时通过
URLDecoder.decode()来进行解码。
package com.shsxt.servlet;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Cookie04 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = URLEncoder.encode("姓名");
String value = URLEncoder.encode("张三");
Cookie cookie = new Cookie(name,value);
// 响应cookie
response.addCookie(cookie);
}
}
5.Cookie的路径
只要访问的路径中包含cookie的path才能访问到该cookie
cookie的路径默认是当前站点名下
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Cookie05 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置cookie能够被当前服务器下所有的项目访问
Cookie cookie = new Cookie("a","AA");
// 设置cookie的路径为服务器根路径
cookie.setPath("/");
// 响应cookie
response.addCookie(cookie);
Cookie cookie2 = new Cookie("b","BB");
// 设置cookie的路径为服务器根路径
cookie2.setPath("/sc04/test/cook");
// 响应cookie
response.addCookie(cookie2);
}
}
三.Session
表示一次会话,会话可以保留指定时间长度。
且在一次会话(一个用户的多次请求)期间共享数据。
1.创建Session对象
request.getSession(); // 如果session不存在则新建session对象;如果session对象存在则获取session
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class Session01 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建session对象
HttpSession session = request.getSession();
// Session的常用方法
String id = session.getId();
System.out.println("会话标识符: " + id);
long createTime = session.getCreationTime();
System.out.println("创建时间: " + createTime);
long lastAccessTime = session.getLastAccessedTime();
System.out.println("最后一次访问时间: " + lastAccessTime);
boolean isNew = session.isNew();
System.out.println("是否是新建session:" + isNew);
}
}
2.session域对象
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class Session02 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建session对象
HttpSession session = request.getSession();
System.out.println("Session02:" + session.getId());
// session域对象
session.setAttribute("uname", "zhangsan");
// request域对象
request.setAttribute("upwd", "123456");
// 请求转发
//request.getRequestDispatcher("Session03").forward(request, response);
// 重定向
response.sendRedirect("Session03");
}
}
3.获取域对象
请求转发
request作用域不会失效,session作用域不会失效
重定向
request作用域会失效,session作用域不会失效
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class Session03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取session对象
HttpSession session = request.getSession();
System.out.println("Session03:" + session.getId());
// 获取session域对象
String uname = (String) session.getAttribute("uname");
System.out.println("Session作用域中的uname:" + uname);
// 获取request作用域
String upwd = (String) request.getAttribute("upwd");
System.out.println("request作用域中的upwd:" + upwd);
}
}
4.Session的失效
1)关闭浏览器 (session的底层是依赖cookie,默认关闭浏览器即失效;JSESSIONID不存在时,后台会新建一个 sesession对象)
2)关闭服务器(非正常关闭服务器时才会销毁,session对象在服务器正常关闭时会钝化到本地磁盘中,下次启动时从
本地磁盘中读取出来,在Tomcat解压包的waork目录下)
3)手动销毁(session.invalidate())
4)服务器默认最大不活动时间
Tomcat的解压缩包下的conf目录下的web.xml中
默认30分钟,单位为分钟
<session-config>
<session-timeout>30</session-timeout>
</session-config>
5)手动设置最大不活动时间
通过 session.setMaxInactiveInterval(int);来设定 session 的最大不活动时间,单位为秒。
通过 getMaxInactiveInterval();方法来查看当前 Session 对象的最大不活动时间。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class Session04 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 得到session对象
HttpSession session = request.getSession();
System.out.println("Session04:" + session.getId());
// 手动销毁
// session.invalidate();
// 获取最大不活动时间
int max = session.getMaxInactiveInterval();
System.out.println("最大不活动时间:" + max);
// 设置指定秒后失效
session.setMaxInactiveInterval(5);
}
}
四.ServletContext 对象
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext对象
// 通过request对象获取
ServletContext servletContext = request.getServletContext();
// 通过session获取
ServletContext servletContext2 = request.getSession().getServletContext();
// 通过servletConfig对象
ServletContext servletContext3 = getServletConfig().getServletContext();
// 直接获取
ServletContext servletContext4 = getServletContext();
// 设置作用域
servletContext.setAttribute("usex", "man");
}
}
Servlet implementation class Servlet02
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取servletContext域对象
String usex = (String) getServletContext().getAttribute("usex");
System.out.println(usex);
// 获取服务器版本
String serverInfo = request.getServletContext().getServerInfo();
System.out.println("获取服务器版本:" + serverInfo);
// 获取项目在服务器中的真实路径
String realPath = request.getServletContext().getRealPath("/");
System.out.println("获取项目在服务器中的真实路径:" + realPath);
}
}