JavaWeb------request and response

Servlet体系结构

Servlet概念

  1. 狭义Servlet是指Java语言中的一个接口,而广义的Servlet是指任何实现Servlet接口的类。
  2. Servlet绝大多数情况下是用来扩展基于HTTP协议的的Web服务器

Servlet生命周期

Init()、service()、destroy()是Servlet生命周期的主要方法,代表了整个Servlet运行的过程。

  1. 当程序运行之后,会创建出一个Servlet实例对象。
  2. Servlet实例对象会首先执行init()方法进行初始化的过程。该方法只会运行一次。
  3. 执行完init()方法之后,Servlet对象会执行service()方法进行工作,后续都只会执行该方法。
  4. 当Servlet对象执行完毕之后,它会调用destroy()方法进行销毁。

Servlet继承关系

Class GenericServlet implement Servlet

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
    private transient ServletConfig config;

    public GenericServlet() {
    }
    
    public void destroy() {
    }

    public String getInitParameter(String name) {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameter(name);
        }
    }

    public Enumeration<String> getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }

    public String getServletInfo() {
        return "";
    }

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }

    public void log(String msg) {
        this.getServletContext().log(this.getServletName() + ": " + msg);
    }

    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public String getServletName() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletName();
        }
    }
}

以上代码是GenericServlet的源码,从代码可以我们看出,GenericServlet类中包含了无参的init()方法无参的destroy()方法所以当我们定义了一个类继承了GenericServlet类的时候,只需要覆盖重写Service()方法

HttpServlet

public abstract class HttpServlet extends GenericServlet implements Serializable {
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";
    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");

    public HttpServlet() {
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected long getLastModified(HttpServletRequest req) {
        return -1L;
    }

    protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        NoBodyResponse response = new NoBodyResponse(resp);
        this.doGet(req, response);
        response.setContentLength();
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_put_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_delete_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    private Method[] getAllDeclaredMethods(Class<?> c) {
        if (c.equals(HttpServlet.class)) {
            return null;
        } else {
            Method[] parentMethods = this.getAllDeclaredMethods(c.getSuperclass());
            Method[] thisMethods = c.getDeclaredMethods();
            if (parentMethods != null && parentMethods.length > 0) {
                Method[] allMethods = new Method[parentMethods.length + thisMethods.length];
                System.arraycopy(parentMethods, 0, allMethods, 0, parentMethods.length);
                System.arraycopy(thisMethods, 0, allMethods, parentMethods.length, thisMethods.length);
                thisMethods = allMethods;
            }

            return thisMethods;
        }
    }

    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Method[] methods = this.getAllDeclaredMethods(this.getClass());
        boolean ALLOW_GET = false;
        boolean ALLOW_HEAD = false;
        boolean ALLOW_POST = false;
        boolean ALLOW_PUT = false;
        boolean ALLOW_DELETE = false;
        boolean ALLOW_TRACE = true;
        boolean ALLOW_OPTIONS = true;

        for(int i = 0; i < methods.length; ++i) {
            Method m = methods[i];
            if (m.getName().equals("doGet")) {
                ALLOW_GET = true;
                ALLOW_HEAD = true;
            }

            if (m.getName().equals("doPost")) {
                ALLOW_POST = true;
            }

            if (m.getName().equals("doPut")) {
                ALLOW_PUT = true;
            }

            if (m.getName().equals("doDelete")) {
                ALLOW_DELETE = true;
            }
        }

        String allow = null;
        if (ALLOW_GET) {
            allow = "GET";
        }

        if (ALLOW_HEAD) {
            if (allow == null) {
                allow = "HEAD";
            } else {
                allow = allow + ", HEAD";
            }
        }

        if (ALLOW_POST) {
            if (allow == null) {
                allow = "POST";
            } else {
                allow = allow + ", POST";
            }
        }

        if (ALLOW_PUT) {
            if (allow == null) {
                allow = "PUT";
            } else {
                allow = allow + ", PUT";
            }
        }

        if (ALLOW_DELETE) {
            if (allow == null) {
                allow = "DELETE";
            } else {
                allow = allow + ", DELETE";
            }
        }

        if (ALLOW_TRACE) {
            if (allow == null) {
                allow = "TRACE";
            } else {
                allow = allow + ", TRACE";
            }
        }

        if (ALLOW_OPTIONS) {
            if (allow == null) {
                allow = "OPTIONS";
            } else {
                allow = allow + ", OPTIONS";
            }
        }

        resp.setHeader("Allow", allow);
    }

    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String CRLF = "\r\n";
        String responseString = "TRACE " + req.getRequestURI() + " " + req.getProtocol();

        String headerName;
        for(Enumeration reqHeaderEnum = req.getHeaderNames(); reqHeaderEnum.hasMoreElements(); responseString = responseString + CRLF + headerName + ": " + req.getHeader(headerName)) {
            headerName = (String)reqHeaderEnum.nextElement();
        }

        responseString = responseString + CRLF;
        int responseLength = responseString.length();
        resp.setContentType("message/http");
        resp.setContentLength(responseLength);
        ServletOutputStream out = resp.getOutputStream();
        out.print(responseString);
    }

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

    private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
        if (!resp.containsHeader("Last-Modified")) {
            if (lastModified >= 0L) {
                resp.setDateHeader("Last-Modified", lastModified);
            }

        }
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }

        this.service(request, response);
    }
}

以上是HttpServlet类的源码,从源码中我们可以发现,HttpServlet抽象类继承自GenericServlet类。其中有俩个方法doPost()方法doGet()方法,当我们定义了一个类,继承了该抽象类,就需要我们重写其中的俩个方法。例如下面的代码:

public class HttpServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
    }
}
定义完成之后,配置Servlet有俩种方式
1. 我们可以在web.xml中进行配置
<servlet>         //servlet用来声明一个Servlet
   <servlet-name>HelloServlet</servlet-name>     //用来定义servlet的名称
   <servlet-class>mypack.HelloServlet</servlet-class>   //用来指定servlet的完全限定的名称。
</servlet>   
<servlet-mapping>   //将URL模式映射到某个Servlet,即该Servlet处理的URL。
   <servlet-name>HelloServlet</servlet-name>    //Servlet的名字,跟上面一致
   <url-pattern>/hello</url-pattern>    //指定相对于Servlet的URL的路径
</servlet-mapping>
2. 可以在Servlet类中用@WebServlet Annotation进行配置
@WebServlet("/demo3") 

Request概念介绍

Request是指在BS架构中,客户端浏览器向服务器发送一次请求

Request常用方法介绍

获取HTTP中请求头数据

String getHeader(String name):通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames()获取所有请求头名称
         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1.获取所有的请求头
        Enumeration<String> headerNames = request.getHeaderNames();
        //2.遍历
        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            //根据名称获取请求头的值
            String value = request.getHeader(name);
            System.out.println(name+"---"+value);
        }

        //获取请求头数据:user-agent
        String agent = request.getHeader("user-agent");
        //判断agent的浏览器版本
        if(agent.contains("Chrome")){
            System.out.println("谷歌");
        }else if(agent.contains("Firefox")){
            System.out.println("火狐");
        }

        //获取请求头数据:referer
        String referer = request.getHeader("referer");
        System.out.println(referer);
    }

获取请求行常用方法

1. 获取请求方式:String getMethod()
2. 获取虚拟目录: String getContextPath()
3. 获取Servlet路径: String getServletPath()
4. 获取get方式请求参数: String getQueryString()
5. 获取请求URI:String getRequestURI() 、StringBuffer getRequestURL()   
6. 获取协议及版本:String getProtocol()
7. 获取客户机的IP地址:String getRemoteAddr()
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //1.获取请求方式:GET
        String method = request.getMethod();
        System.out.println(method);

        //2.获取虚拟目录     /dat14
        String contextPath = request.getContextPath();
        System.out.println(contextPath);

        //3.获取Servlet路径    /demo1
        String servletPath = request.getServletPath();
        System.out.println(servletPath);

        // 4.获取get方式请求参数:name=zhangsan
        String queryString = request.getQueryString();
        System.out.println(queryString);

        //5.1获取请求URI:/day14/demo1
        //5.2 StringBuffer getRequestURL()
        String requestURI = request.getRequestURI();
        StringBuffer requestURL = request.getRequestURL();
        System.out.println(requestURI);
        System.out.println(requestURL);

        //6.获取协议及版本:HTTP/1.1
        String protocol = request.getProtocol();
        System.out.println(protocol);

        //7.获取客户机的IP地址:
        String remoteAddr = request.getRemoteAddr();
        System.out.println(remoteAddr);
    }

获取请求体数据

获取流对象:
  BufferedReader getReader():获取字符输入流,只能操作字符数据
  ServletInputStream getInputStream():获取字节输入流,可以操作所有类型的数据
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求消息体

        //1.获取字符流
        BufferedReader br = request.getReader();
        //2.读取数据
        String line = null;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
    }

其他功能

1.获取请求参数通用方式
String getParameter(String name) 根据参数名称获取参数值 username=zs&&password=123
String[] getParameterValues(String name) 根据参数名称获取参数值的数组 hobby=game&&hobby=ball
Enumeration<String> getParameterNames() 获取所有请求的参数名称
Map<String, String[]> getparameterMap() 获取所有参数的map集合


2.请求转发:一种在服务器内部的资源跳转方式
步骤:
  1.通过request对象获取请求转发器对象 RequestDispatcher getRequestDispatcher(String path)
  2.使用RequestDispatcher对象来进行转发
         forward(request,response)

 特点:浏览器地址栏路径(url)不发生变化
      只能转发到当前服务器内部资源中
      转发只是一次请求



3.共享数据:
域对象:一个有作用范围的对象,可以在范围内共享数据
  request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

   方法:
          1.setAttribute(String name,Object obj):存储数据
          2.Object getAttitude(String name):通过键获取值
	      3.void removeAttribute(String name):通过键移除键值对


4.获取ServletContext
 ServletContext  getServletContext()
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //出现乱码问题是设置请求request编码
        //request.setCharacterEncoding("utf-8");

         //post 获取请求参数

        //根据参数名称获取参数值
        String username = request.getParameter("username");
//      System.out.println(username);

        //根据参数名称获取参数值的数组
        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby:hobbies
             ) {
            System.out.println(hobby);
        }

        //获取所有请求的参数名称
        Enumeration<String> parameterNames = request.getParameterNames();
        while(parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();
            System.out.println(name);
            String value = request.getParameter(name);
            System.out.println(value);
            System.out.println("-------------------");
        }


        //获取所有参数的map集合
        Map<String, String[]> parameterMap = request.getParameterMap();
        //遍历
        Set<String> keyset = parameterMap.keySet();
        for (String name:keyset
             ) {
            //根据键获取值
            String[] values = parameterMap.get(name);
            System.out.println(name);
            for (String value:values
                 ) {
                System.out.println(value);
            }
            System.out.println("--------------");
        }
     
    }

Response概念介绍

在BS架构中,服务器给客户端浏览器反馈结果。

常见的状态码

状态码说明
200访问成功
302资源重定向
304访问缓存
404请求路径没有对应资源
405请求方式没有对应doPost或doGet方法
500服务器内部出现异常

重定向

重定向和转发的区别

重定向    response.sendDedirect():
  1.地址栏发生变化
  2.至少请求了俩次,切不能使用request对象共享数据
  3.重定向可以访问其他站点(服务器)资源

转发    request.getRequestDispatcher()
  1.地址栏不变
  2.转发只是一次请求,可以用request对象来共享资源
  3.转发只能访问当前服务器下的资源

重定向的方法

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ziyuan1....");


        //访问ziyuan1,会自动跳转到ziyuan2
        //1.设置状态码为3.2
//        response.setStatus(302);

        //2.设置响应头location
//        response.setHeader("location","/ziyuan2");

        //动态获取虚拟目录
        String contextPath = request.getContextPath();

        //简单的重定向方法
        response.sendRedirect(contextPath+"/ziyuan2");
    }

Response常见方法

输出字符数据

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
        设置编码的方法
           //获取流对象之前,设置流的默认编码:ISO-8859-01 设置为:GBK
           //response.setCharacterEncoding("utf-8");

           //告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码来解码
           //response.setHeader("content-type","text/html;charset=utf-8")
           
*/
        //简单的形式来设置编码,作用同setHeader()
        response.setContentType("text/html;charset=utf-8");

        //1.获取字符输出流
        PrintWriter pw = response.getWriter();

        //2.输出数据
        pw.write("你好,hello response");
    }

输出字节数据

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");

        //1.获取字节输出流
        ServletOutputStream sos = response.getOutputStream();

        //2.输出数据      hello是字符,getBytes()是获取字节数组
        sos.write("hello.".getBytes("utf-8"));
    }

声明

本文是作者在学习JavaWeb中的一些笔记,希望能够帮助到大家。作者才疏学浅,若有错误,欢迎批评指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值