Servlet学习笔记(四):Servlet的请求与响应

来源:互联网 发布:台湾误发导弹 知乎 编辑:程序博客网 时间:2024/04/30 12:31

客户端浏览器发送一个请求,服务器作出一系列操作后作出一个响应,发送给客户端,完成一次Web过程过程操作。Web编程的过程就是通过分析客户需要什么信息或者进行了什么操作,然后进行一系列的处理,最后通过响应结果显示给客户。即一次请求-响应的过程。


一、请求-HttpServletRequest对象


客户端浏览器的请求被封装成一个HttpServletRequest对象。所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件,客户端的IP地址甚至客户端操作系统都包含在HttpServletRequest对象中。


封装信息以及获取的方法:

1、编码信息和文档类型。

1)编码信息:设置与获取编码信息

A、request.setCharacterEncoding("UTF-8") :设置编码,统一使用 setCharacterEncodingFilter 

B、request.getCharacterEncoding() :获取编码方法。

2)文档信息:设置与获取文档信息

A、response.setContentType("text/html") :设置 文档类型为HTML类型。这边可以设置输出数据的类型,text/html、image/jpeg、application/msword

B、request.getContentType() :获取文档类型。

3)代码示例:

// 1-设置编码方式,可以用时setCharacterEncodingFilter过滤器统一处理request.setCharacterEncoding("UTF-8");// 设置 request 的编码方式response.setCharacterEncoding("UTF-8");// 设置 response 的编码方式response.setContentType("text/html");// 设置 文档类型为HTML类型request.getCharacterEncoding();request.getContentType();

2、服务器信息。

1)Authorization信息:request.getAuthType()

2)本地IP, 即服务器IP:request.getLocalAddr()

A、实际项目中,一般会用到java.net包下 InetAddress 来获取服务器的真实 IP 地址:

// 2-1 实际项目中,一般会用到java.net包下 InetAddress 来获取服务器的真实 IP 地址String myLocalIp = InetAddress.getLocalHost().getHostAddress();// 本地地址,服务器IP地址logger.debug("利用java.net包下 InetAddress 来获取服务器真实 IP 地址: " + myLocalIp);

B、Linux下获取服务器IP地址,InetAddress获取IP的方法在windows下没有问题

// InetAddress获取IP的方法在windows下没有问题,在Linux有问题,主要是在linux下返回的是/etc/hosts// 中配置的ip地址,而不是网卡的绑定地址。现在改用网卡的绑定地址,可以取到本机的ip地址:// 利用NetworkInterface 可以封装成一个方法String serverip = null;Enumeration<NetworkInterface> netInterfaces = null;netInterfaces = NetworkInterface.getNetworkInterfaces();while (netInterfaces.hasMoreElements()) {NetworkInterface ni = netInterfaces.nextElement();// System.out.println("DisplayName:" + ni.getDisplayName());// System.out.println("Name:" + ni.getName());Enumeration<InetAddress> ips = ni.getInetAddresses();while (ips.hasMoreElements()) {InetAddress ip = ips.nextElement();// IP地址分为普通地址和特殊地址。利用InetAddress类提供的十个方法来确定一个IP地址是否是一个特殊的IP地址。// 判断是否地区本地地址if (ip.isSiteLocalAddress()) {serverip = ip.getHostAddress();break;}}}logger.debug("Linux下 来获取服务器真实 IP 地址: " + serverip);


3)本地名称, 即服务器名称: request.getLocalName()

4)本地端口号, 即Tomcat 端口号: request.getLocalPort()

5)本地环境: Locale locale = request.getLocale();

Locale locale = request.getLocale();// 本地环境String localLangurage = getLocaleLangurage(locale);// 语言环境String localCountry = locale.getCountry();// 国家

6)服务器名称:request.getServerName()

7)服务器端口:request.getServerPort()


3、客户端信息。

1)远程IP,即客户端IP:request.getRemoteAddr()

2)远程端口,即客户端端口:request.getRemotePort()

3)客户端的IP,往往会有代理,所以一般的获取方法,需要处理代理信息:

// 客户端的IP,往往会有代理,所以一般的获取方法,需要处理信息String realCusIp = getRealCusIpAddr(request);//真实客户端IP地址/**   * 获得用户真实IP   *   * @param request 请求对象   * @return 真实IP地址   */  public String getRealCusIpAddr(HttpServletRequest request) {      String ip = request.getHeader("x-forwarded-for");      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getHeader("Proxy-Client-IP");      }      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getHeader("WL-Proxy-Client-IP");      }      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getRemoteAddr();      }      return ip;  } 

4)远程用户:request.getRemoteUser()。如果提供了Authorization头,则代表其用户部分。它代表发出请求的用户的名字。


4、获取请求信息。

1)获取本次请求的协议信息

A、协议,这里为HTTP协议:request.getProtocol()

B、协议头,这里为Http: request.getScheme()


2)获取头信息 利用浏览器都可以看到

A、浏览器支持的格式,访问Accept的HTTP头: request.getHeader("accept")

B、从哪个页面单机链接到了本页:直接输入为空。request.getHeader("referer")

C、User Agent 信息:request.getHeader("user-agent")

D、其他:request.getHeader("Host")  | request.getHeader("Accept-Language") | 

 request.getHeader("Accept-Encoding") | request.getHeader("Connection")| 

  request.getHeader("Cookie");


3)获取本次请求的一些基本信息

A、访问的方式:Get还是Post。request.getMethod()

B、查询字符串,即访问时 ? 后面的字符串。request.getQueryString()

C、用户请求的URI:request.getRequestURI(),权限使用。

D、用户请求的URL: request.getRequestURL()

用户请求的URL: http://localhost:8080/JavaWeb/servlet/RequestServlet,那么用户请求的URI为: /JavaWeb/servlet/RequestServlet 


4)获取请求的Servlet的信息

A、Context路径:request.getContextPath()。上下文路径,一般是“/工程名”,如:/JavaWeb

B、Servlet的路径: request.getServletPath()。访问的servlert的路径,一般可以在filter中使用,作为拦截。如:/servlet/RequestServlet 。

C、URL中Servlet路径之后、查询字符串之前的那部分: request.getPathInfo()

D、映射到服务器实际路径之后的路径信息: getPathTranslated()

F、request.getServletPath() 和 request.getPathInfo()的差别,见文章。


5、其他信息。

1)客户端Session的ID: request.getRequestedSessionId()

2)获取Session信息:request.getSession()

3)获取CooKie信息:request.getCookies()

4)当前授权用户的名称: request.getUserPrincipal()

5)本Servlet运行的服务器信息:this.getServletContext().getServerInfo() 


6、附加补充:利用以下四个方法,获取绝对路径。也可以单独使用getContextPath()获取相对路径。

String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

在实际项目中可以放入某个公用页面,这样可以解决大部分的路径问题。


7、完整的代码。

package servlet.base;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.net.UnknownHostException;import java.security.Principal;import java.util.Enumeration;import java.util.Locale;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.log4j.Logger;import util.IPSeeker;/** *  * RequestServlet.java *  * @title HttpServletRequest-请求 * @description * @author SAM-SHO * @Date 2014-9-26 */public class RequestServlet extends HttpServlet {private static final long serialVersionUID = 1L;// 一定要把log4j的jar包放入lib目录下,不能只是添加build path,不然类加载器加载不到public Logger logger = Logger.getLogger(this.getClass());public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {log("使用servlet内置的log, 调用了doGet方法");doService(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doService(request, response);}/** * 通用业务方法 *  * @param request * @param response * @throws UnsupportedEncodingException * @throws UnknownHostException * @throws SocketException */private void doService(HttpServletRequest request, HttpServletResponse response) {try {/** 1-编码方法 ************************************************************************/// 1-设置编码方式,可以用时setCharacterEncodingFilter过滤器统一处理request.setCharacterEncoding("UTF-8");// 设置 request 的编码方式response.setCharacterEncoding("UTF-8");// 设置 response 的编码方式response.setContentType("text/html");// 设置 文档类型为HTML类型request.getCharacterEncoding();request.getContentType();/** 2-获取服务器信息 ********************************************************************/// 2-0-基本的获取服务器信息String authType = request.getAuthType();// Authorization头String localAddr = request.getLocalAddr();// 本地IP, 即服务器IPString localName = request.getLocalName();// 本地名称, 即服务器名称int localPort = request.getLocalPort();// 本地端口号, 即Tomcat 端口号Locale locale = request.getLocale();// 本地环境String localLangurage = getLocaleLangurage(locale);// 语言环境String localCountry = locale.getCountry();// 国家logger.debug("验证: " + authType + " |服务器IP: " + localAddr + " |服务器名称: " + localName + " |端口号: " + localPort + " |用户的语言环境: " + localLangurage + " |国家: " + localCountry);String serverName = request.getServerName();// 服务器名称int serverPort = request.getServerPort();// 服务器端口logger.debug("服务器名称: " + serverName + " |服务器端口: " + serverPort);// 2-1 实际项目中,一般会用到java.net包下 InetAddress 来获取服务器的真实 IP 地址String myLocalIp = InetAddress.getLocalHost().getHostAddress();// 本地地址,服务器IP地址logger.debug("利用java.net包下 InetAddress 来获取服务器真实 IP 地址: " + myLocalIp);// 2-2// InetAddress获取IP的方法在windows下没有问题,在Linux有问题,主要是在linux下返回的是/etc/hosts// 中配置的ip地址,而不是网卡的绑定地址。现在改用网卡的绑定地址,可以取到本机的ip地址:// 利用NetworkInterface 可以封装成一个方法String serverip = null;Enumeration<NetworkInterface> netInterfaces = null;netInterfaces = NetworkInterface.getNetworkInterfaces();while (netInterfaces.hasMoreElements()) {NetworkInterface ni = netInterfaces.nextElement();// System.out.println("DisplayName:" + ni.getDisplayName());// System.out.println("Name:" + ni.getName());Enumeration<InetAddress> ips = ni.getInetAddresses();while (ips.hasMoreElements()) {InetAddress ip = ips.nextElement();// IP地址分为普通地址和特殊地址。利用InetAddress类提供的十个方法来确定一个IP地址是否是一个特殊的IP地址。// 判断是否地区本地地址if (ip.isSiteLocalAddress()) {serverip = ip.getHostAddress();break;}}}logger.debug("Linux下 来获取服务器真实 IP 地址: " + serverip);/** 3-获取客户端信息 *********************************************************************/// 3- 获取客户端基本信息String remoteAddr = request.getRemoteAddr();// 远程IP,即客户端IPint remotePort = request.getRemotePort();// 远程端口,即客户端端口String remoteUser = request.getRemoteUser();// 远程用户,如果提供了Authorization头,则代表其用户部分。它代表发出请求的用户的名字。logger.debug("客户端IP: " + remoteAddr + " |客户端端口: " + remotePort + " |远程用户: " + remoteUser);// 客户端的IP,往往会有代理,所以一般的获取方法,需要处理信息String realCusIp = getRealCusIpAddr(request);//真实客户端IP地址logger.debug("客户端真实IP,附带代理的IP地址: "+realCusIp);/** 4-获取请求信息 *********************************************************************/// 4-1 获取本次请求的协议信息String protocol = request.getProtocol();// 协议,这里为HTTP协议String scheme = request.getScheme();// 协议头,这里为Httplogger.debug("协议: " + protocol + " |协议头: " + scheme);// 4-2 获取头信息 利用浏览器都可以看到String accept = request.getHeader("accept");// 浏览器支持的格式,访问Accept的HTTP头String referer = request.getHeader("referer");// 从哪个页面单机链接到了本页String userAgent = request.getHeader("user-agent");// User Agent 信息,// 包括操作系统及版本号、浏览器类型及版本号request.getHeader("Host");       request.getHeader("Accept-Language");request.getHeader("Accept-Encoding");request.getHeader("Connection");request.getHeader("Cookie");logger.debug("浏览器支持的格式: " + getAccept(accept) + " |从哪个页面单机链接到了本页: " + referer + " |操作系统信息: " + getOS(userAgent)+" |客户端浏览器信息 "+ getNavigator(userAgent));// 4-3 获取本次请求的一些基本信息String method = request.getMethod();// 访问的方式:Get还是PostString queryString = request.getQueryString();// 查询字符串,即访问时 ? 后面的字符串String requestURI = request.getRequestURI();// 用户请求的URIStringBuffer requestURL = request.getRequestURL();// 用户请求的URLlogger.debug("访问的方式: " + method + " |查询字符串,即访问时 ? 后面的字符串: " + queryString + " |用户请求的URI: " + requestURI + " |用户请求的URL: " + requestURL);// 4-4 获取请求的Servlet的信息String contextPath = request.getContextPath();// Context路径String servletPath = request.getServletPath();// Servlet的路径String pathInfo = request.getPathInfo();// URL中Servlet路径之后、查询字符串之前的那部分。String pathTranslated = request.getPathTranslated(); // 映射到服务器实际路径之后的路径信息。/** 5-其他信息 *********************************************************************/// 5-1 其他信息String requestedSessionId = request.getRequestedSessionId(); // 客户端Session的IDHttpSession session = request.getSession(); // 获取Session信息Cookie[] cookies = request.getCookies(); //获取CooKie信息Principal userPrincipal = request.getUserPrincipal(); // 当前授权用户的名称String serverInfo = this.getServletContext().getServerInfo(); // 本Servlet运行的服务器信息logger.debug("Context路径: " + contextPath + " |Servlet的路径: " + servletPath + " |本Servlet运行的服务器信息: " + serverInfo + " |客户端Session的ID: " + requestedSessionId);} catch (Exception e) {e.printStackTrace();}}/** * linux下获取服务器真实 IP *  * @return */public static String getServerIP() {String serverip = "";try {// InetAddress addr = InetAddress.getLocalHost();// serverip = addr.getHostAddress();// Modify by YiQiang 20130710// InetAddress获取IP的方法在windows下没有问题,在Linux有问题(下只是读取/etc/hosts下的配置)Enumeration<NetworkInterface> netInterfaces = null;netInterfaces = NetworkInterface.getNetworkInterfaces();while (netInterfaces.hasMoreElements()) {NetworkInterface ni = netInterfaces.nextElement();Enumeration<InetAddress> ips = ni.getInetAddresses();while (ips.hasMoreElements()) {InetAddress ip = ips.nextElement();if (ip.isSiteLocalAddress()) {serverip = ip.getHostAddress();break;}}}} catch (Exception ex) {serverip = "127.0.0.1";}return serverip;}/** * 用户的语言环境 *  * @param locale * @return 语言环境名称 */private String getLocaleLangurage(Locale locale) {if (Locale.SIMPLIFIED_CHINESE.equals(locale))return "简体中文";if (Locale.TRADITIONAL_CHINESE.equals(locale))return "繁体中文";if (Locale.ENGLISH.equals(locale))return "英文";if (Locale.JAPANESE.equals(locale))return "日文";return "未知语言环境";}/** * @param accept * @return 客户端浏览器接受的文件类型 */private String getAccept(String accept) {StringBuffer buffer = new StringBuffer();if (accept.contains("image/gif"))buffer.append("GIF 文件, ");if (accept.contains("image/x-xbitmap"))buffer.append("BMP 文件, ");if (accept.contains("image/jpeg"))buffer.append("JPG 文件, ");if (accept.contains("application/vnd.ms-excel"))buffer.append("Excel 文件, ");if (accept.contains("application/vnd.ms-powerpoint"))buffer.append("PPT 文件, ");if (accept.contains("application/msword"))buffer.append("Word 文件, ");return buffer.toString().replaceAll(", $", "");}/** * @param ip *            IP地址 * @return IP地址对应的物理位置 */private String getAddress(String ip) {try {return IPSeeker.getInstance().getAddress(ip);} catch (Exception e) {e.printStackTrace();}return "未知区域";}/** * @param userAgent * @return 客户端浏览器信息 */private String getNavigator(String userAgent) {if (userAgent.indexOf("TencentTraveler") > 0)return "腾讯浏览器";if (userAgent.indexOf("Maxthon") > 0)return "Maxthon浏览器";if (userAgent.indexOf("MyIE2") > 0)return "MyIE2浏览器";if (userAgent.indexOf("Firefox") > 0)return "Firefox浏览器";if (userAgent.indexOf("MSIE") > 0)return "IE 浏览器";if(userAgent.indexOf("Chrome") > 0)return "Chrome 浏览器";return "未知浏览器";}/** * @param userAgent * @return 客户端操作系统 */private String getOS(String userAgent) {if (userAgent.indexOf("Windows NT 5.1") > 0)return "Windows XP";if (userAgent.indexOf("Windows 98") > 0)return "Windows 98";if (userAgent.indexOf("Windows NT 5.0") > 0)return "Windows 2000";if (userAgent.indexOf("Linux") > 0)return "Linux";if (userAgent.indexOf("Unix") > 0)return "Unix";if (userAgent.indexOf("Windows NT 6.1") > 0)return "Windows 7";return "未知";}/**   * 获得用户真实IP   *   * @param request 请求对象   * @return 真实IP地址   */  public String getRealCusIpAddr(HttpServletRequest request) {      String ip = request.getHeader("x-forwarded-for");      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getHeader("Proxy-Client-IP");      }      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getHeader("WL-Proxy-Client-IP");      }      if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {          ip = request.getRemoteAddr();      }      return ip;  } }

8、使用头信息request.getHeader("referer"), 实现防盗链。


二、响应-HttpServletResponse

服务器对客户端浏览器作出的响应被封装成一个HttpServletResponse 对象。要对浏览器进行操作,只要要操作HttpServletResponse 对象就可以了。通过HttpServletResponse.getWriter()获得一个 PrintWriter 对象,该对象为 OutputStream 的子类。


1、HttpServletResponse.getWriter():对象只能写字符型的数据。HttpServletResponse.getOutputStream ():写二进制数据,如输出图片等。注意:这两个方法不能同时使用,特别是多层转发的时候,使用的还是同一个request对象,不能同时调用这两个方法。(getOutputStream () has already bean called for this response)

2、输出必须设置输出类型:response.setContentType("image/jpeg"),需要与输出方式统一。例子:输出图片验证码:

package servlet.base;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.IOException;import java.util.Random;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGImageEncoder;/** *  * IdentityServlet.java *  * @title * @description * @author SAM-SHO * @Date 2014-9-27 */public class IdentityServlet extends HttpServlet {private static final long serialVersionUID = -479885884254942306L;// 随机字符字典public static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };public static Random random = new Random();// 随机数public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("image/jpeg");// 设置输出类型String randomString = getRandomString();// 获取随机字符串request.getSession(true).setAttribute("randomString", randomString);// 放入sessionint width = 100; // 图片宽度int height = 30; // 图片高度Color color = getRandomColor();// 随机颜色,用于背景色Color reverse = getReverseColor(color);// 反色,用于前景色BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//创建一个彩色图片Graphics2D g = bi.createGraphics();// 获取绘图对象g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));//设置字体g.setColor(color);//设置颜色g.fillRect(0, 0, width, height);// 绘制背景g.setColor(reverse);//设置颜色g.drawString(randomString, 18, 20);//绘制随机字符//画最多100个噪音点for (int i = 0, n = random.nextInt(100); i < n; i++) {g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);}// 转成JPEG格式ServletOutputStream out = response.getOutputStream();JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);//编码器encoder.encode(bi);//对图片进行编码out.flush();}/** * 获取 6 位 随机数 *  * @return */public static String getRandomString() {StringBuffer buffer = new StringBuffer();for (int i = 0; i < 6; i++) {// 循环 6 次buffer.append(CHARS[random.nextInt(CHARS.length)]);// 每次取一个随机字符}return buffer.toString();}/** * 获取随机的颜色 *  * @return */public static Color getRandomColor() {return new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255));}/** * 返回某颜色的反色 *  * @param c * @return */public static Color getReverseColor(Color c) {return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());}/** * 测试 * @param args */public static void main(String[] args) {System.out.println(getRandomString());}}



3、控制浏览器是否缓存。

1)不缓存。

response.setHeader("progma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setHeader("Cache-Control", "no-store");response.setDateHeader("Expires", 0);//时间头


2)利用Expires时间头,控制页面缓存。记得加上当前时间。System.currentTimeMillis()

//设置缓存 一定要是当前时间 + 控制的缓存时间response.setDateHeader("Expires", System.currentTimeMillis() + 1000*3600);


4、利用HttpServletResponse实现下载:

// 2-1实现下载// 注意中文的文件名文件下载时,注意编码 URLEncoder// 使用getRealPath(),为了实现文件名称的显示//String realPath = this.getServletContext().getRealPath("/downLoad/mcm.png");String realPath = this.getServletContext().getRealPath("/downLoad/蒙奇奇.jpg");//中文System.out.println("文件的绝对路径: " + realPath);String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);System.out.println("文件的名称为: " + fileName);//设置浏览器下载response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));// 固定输出InputStream in = null;OutputStream out = null;try {in = new FileInputStream(realPath);int len = 0;byte[] buffer = new byte[1024];out = response.getOutputStream();while ((len = in.read(buffer)) > 0) {out.write(buffer, 0, len);}}finally{if(in != null) {try {in.close();} catch (Exception e) {}}}


三、Servlet的跳转


利用Servlet的跳转,实现了MVC框架,把程序分成三个独立模块:业务模块(Model)、视图模块(View)、控制模块(Control)。其中Model负责处理业务,View负责显示数据,Control负责控制。在struts框架中三个部分分别为3个Servlet,程序在3个Servlet之间跳转。

Servlet的跳转有两种方式:转发(Forward)和重定向(Redirect)。


1、转发(Forward):

是通过 RequestDispatcher 对象的 forward()方法实现。RequestDispatcher 可以通过HttpServletRequest 的getRequestDispatcher()方法获得。或者使用ServletContext.getRequestDispatcher()方法获取。

1)代码:

RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet/LifecyclesServlet");dispatcher.forward(request, response);

2)getRequestDispatcher()方法的参数必须为以“/”开始,“/”表示本Web应用程序的根路径。如果要跳转到Servlet为http://localhost:8080/servlet/RequestServlet。则参数应该为“/servlet/RequestServlet”。


3)当使用Forward形式跳转Servlet时,地址栏会显示跳转前的Servlet访问地址。因为该跳转是在服务器端实现,客户端浏览器并不知道该跳转动作。也就是说Forward跳转对客户端浏览器是透明的。

4)Forward是最常用的方式。在struts等框架中,都是用Servlet来处理用户请求,把结果通过request.setAttribute()放到 request 中,然后Forward到JSP显示。

5)当执行Forward动作的时候不能有任何输出到达客户端,否则会抛出illegalStateException。也就是在 Forward 之前尽量不要使用 out.println()语句向客户端输出结果。

6)转发:同一个HttpServletRequest 这时,web数据的共享要使用Request 域即可。



2、重定向(Redirect)

1)重定向是利用服务器返回的状态来实现的。客户端浏览器请求服务器的时候,服务器端会返回一个状态码。服务器端通过 HttpServletResponse 的 setStatus()方式设置状态码。如果服务器返回301 或者302,则浏览器会到新的网址重新请求该资源。状态码的意思如下:

2)301 、302都表示重定向,区别是 301是永久性重定向,302是临时性重定向。下面的代码将访问该Servlet的请求重定向到另一个网址。

response.setStates(HttpServletResponse.SC_MOVED_PERMANENTLY);//设置状态码为301

response.setHeader("Location","http://www.baidu.com") 新网址


3)HttpServletResponse 类中把重用的状态码封装成了静态常量。并且把setStates()与setHeader()方法封装成另一个方法sendRedirect(String location),只需要调用sendRedirect就能实现重定向。

4)与转发不同,重定向(Redirect)的跳转是在客户端实现的。实际上客户端浏览器请求了 2 次服务器,第1 次获取重定向的状态码与重定向的网址,第 2 次访问真实地址。

5)重定向:不同的HttpServletRequest 对象,每一次访问都会new一个HttpServletRequest 对象。这时,web数据的共享要使用 session 域和 context 域。


// request域的数据,转发可以获取,重定向获取不到String data = "12345";request.setAttribute("data", data);/*********   转发    *******************/// 转发,可以获取request域的数据。只有一个请求,服务器跳转。url不会变化。// 1-1 获取 RequestDispatcher对象,然后转发RequestDispatcher rd = request.getRequestDispatcher("/MyJsp.jsp");RequestDispatcher rd2 = getServletContext().getRequestDispatcher("/MyJsp.jsp");rd.forward(request, response);rd2.forward(request, response);// 2-1 直接转发request.getRequestDispatcher("/MyJsp.jsp").forward(request, response);getServletContext().getRequestDispatcher("/MyJsp.jsp").forward(request, response);/*********   重定向    *******************/// 重定向 ,2次request请求,客户端跳转跳转,url显示第二次跳转的url地址,不能获取request域的数据。response.sendRedirect("/MyJsp.jsp");

3、自动刷新(Refresh)

自动刷新不仅可以实现一段时间之后自动跳转到另一个页面,还可以实现一段时间之后刷新本页面。Servlet中通过设置HttpServletResponse 对象的Header属性实现自动刷新效果。例如:

response.setHeader("Refresh","1000; url=http://www.baidu.com")

1)其中 1000 为时间,单位为毫秒。
2)URL参数指定的网址就是1 秒之后跳转的页面。当URL设置的路径为Servlet自己的路径时,就会每隔1秒钟自动舒鑫页面一次。

3)自动刷新与重定向原理是差不多。如果时间设为 0,把URL设为另一个网址,效果就是重定向。

response.setHeader("Refresh","0; url=http://www.baidu.com")



0 0