JavaEE 学习专题服务端相关

服务器处理请求

2018-07-23  本文已影响19人  咸鱼有梦想呀

request和response都是服务器创建的对象
参考文章Http协议

服务器处理请求流程
服务器每次收到请求时,都会为这个请求开辟一个新的线程。
服务器会把客户端的请求数据封装到request对象中,request就是请求数据的载体。
服务器还会创建response对象,这个对象与客户端连接在一起,它可以用来向客户端发送响应。

一、request

request封装了客户端所有的请求
request是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest。

request对象的功能

小栗子:
获取客户端的IP地址、获取请求方式、获取User-Agent,得到客户端的信息(操作系统 浏览器)。

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;

/**
 * 获取客户端的IP地址、获取请求方式、获取User-Agent,得到客户端的信息(操作系统 浏览器)。
 *
 */
public class AServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String addr = request.getRemoteAddr();//获取客户端的IP地址
        
        response.sendRedirect("http://www.baidu.com");
        if(true) return;
        
        System.out.println("IP: " + addr);
        System.out.println("请求方式:" + request.getMethod());//获取请求方式
        String userAgent = request.getHeader("User-Agent");//获取名为User-Agent的请求头!
        // 是否包含Chrome,如果包含,说明用户使用的是google浏览器
        if(userAgent.toLowerCase().contains("chrome")) {
            System.out.println("您好:" + addr + ", 你用的是谷歌");
        } else if(userAgent.toLowerCase().contains("firefox")) {
            System.out.println("您好:" + addr + ", 你用的是火狐");
        } else if(userAgent.toLowerCase().contains("msie")) {
            System.out.println("您好:" + addr + ", 你用的是IE");
        }
    }
}
运行结果 获取请求url

在什么时候使用请求转发和请求包含
需要多个Servlet协作才能完成,需要在一个Servlet跳到另一个Servlet。

小栗子:请求转发
OneServlet.java

package cn.itcast.servlet.forward;

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;

/**
 * 请求转发
 *
 */
public class OneServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("OneServlet...");
        response.setHeader("aaa", "AAA");//设置响应头
        response.getWriter().print("a");//设置响应体

//如果要转发给其他页面做,就不要在本页面做太多动作,不然会抛异常
//如果执行下面注释的代码就会抛异常
//      for(int i = 0; i < 1024 * 24 + 1; i++) {
//          response.getWriter().print("a");//设置响应体
//      }

        //请求转发
        request.getRequestDispatcher("/TwoServlet").forward(request, response);
    }
}


//只保留请求头
内容显示TwoServlet.java的内容

同一请求范围内使用request.setAttribute()、request.getAttribute()来传值!前一个Servlet调用setAttribute()保存值,后一个Servlet调用getAttribute()获取值。

二、response

response是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletResponse。

ServletResponse和HttpServletResponse的区别
ServletResponse是与协议无关的类型
HttpServletResponse是与协议相关的类型

1.response对象的功能

小栗子:发送404

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;

/**
 * 发送404状态码
 *
 */
public class AServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.sendError(404, "您访问的资源存在,就不给你看!");
    }
}

小栗子:

①发送302,设置Location头,完成重定向

重定向思路图
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;
/**
 * 重定向!
 *
 * 用户请求BServlet,然后BServlet响应302,给出Location头
 */
public class BServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("BServlet");
        
        /*
         * 重定向:
         * 1. 设置Location
         * 2. 发送302状态码
         */
//      response.setHeader("Location", "/text/CServlet");
//                                     项目名/Servlet路径(请求url)
//      response.setStatus(302);
        
        //快捷的重定向方法
        response.sendRedirect("/text/CServlet");
    }
}

②定时刷新:设置Refresh头,定时重定向!

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;

/**
 * 定时刷新
 * 
 * 设置一个Refresh,它表示定时刷新!
 */
public class DServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /*
         * 下面是用来发送响应体!
         */
        PrintWriter writer = response.getWriter();
        writer.print("欢迎XXX登录!5秒钟后会自动跳转到主页!您看到的一定是乱码!");
        /*
         * 设置名为Refresh的响应头
         */
        response.setHeader("Refresh", "5;URL=/test/EServlet");
    }
}

注意:在一个请求中,不能同时使用这两个流!也就是说,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流。不然会抛出IllegalStateException异常。

小栗子:
使用ServletOutputStream发送字节数据

import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

public class GServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
//使用ServletOutputStream发送字节数据(文本)
/*
        String s = "Hello outputStream";
        byte[] bytes = s.getBytes();
        response.getOutputStream().write(bytes);
*/
//使用ServletOutputStream发送字节数据(图片)
        // 把一张图片读取到字节数组中
        String path = "F:/F/白冰.jpg";
        FileInputStream in = new FileInputStream(path);
//      byte[] bytes = IOUtils.toByteArray(in);//读取输入流内容的字节到字节数组中。
//      response.getOutputStream().write(bytes);
        IOUtils.copy(in, response.getOutputStream());
    }
}

三、编码

常见字符编码:iso-8859-1(不支持中文)、gb2312、gbk、gb18030(系统默认编码,中国的国标码)、utf-8(万国码,支持全世界的编码,所以我们使用这个)

一般会在以下情况中出现编码问题

不乱码:
在是用getWriter()方法之前,先调用`response。setContentType("text/html;charset=utf-8");

响应编码

请求编码处理分为两种:GET和POST
1)GET请求编码处理
tomcat8的默认编码已经是utf-8,所以不用变了
2)POST请求编码处理
String username = new String(request.getParameter("iso-8859-1"), "utf-8");
在获取参数之前调用request.setCharacterEncoding("utf-8");

请求编码

代码说明:

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;

public class AServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        /*
         * 1. 在获取参数之前,需要先调用request.setCharacterEncoding("utf-8");
         * 2. 使用getParameter()来获取参数
         */
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        System.out.println(username);
    }
}

上一篇 下一篇

猜你喜欢

热点阅读