客户端浏览器发送一个请求,服务器作出一系列操作后作出一个响应,发送给客户端,完成一次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, 即服务器IP
- String 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,即客户端IP
- int 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();// 协议头,这里为Http
- logger.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还是Post
- String queryString = request.getQueryString();// 查询字符串,即访问时 ? 后面的字符串
- String requestURI = request.getRequestURI();// 用户请求的URI
- StringBuffer requestURL = request.getRequestURL();// 用户请求的URL
- logger.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的ID
- HttpSession 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);// 放入session
- int 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);//时间头
- //设置缓存 一定要是当前时间 + 控制的缓存时间
- 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属性实现自动刷新效果。例如:
1)其中 1000 为时间,单位为毫秒。
- response.setHeader("Refresh","1000; url=http://www.baidu.com")
2)URL参数指定的网址就是1 秒之后跳转的页面。当URL设置的路径为Servlet自己的路径时,就会每隔1秒钟自动舒鑫页面一次。
3)自动刷新与重定向原理是差不多。如果时间设为 0,把URL设为另一个网址,效果就是重定向。
- response.setHeader("Refresh","0; url=http://www.baidu.com")