[有书共读]Java Web高级编程

JavaWeb高级编程 -- 篇3

在Java EE平台中,Servlet用于接收和响应终端用户的请求。Servlet在Java EE API规范中的定义如下:

Servlet是一个运行在Web服务器中的Java小程序。Servlet将会接收和响应来自Web客户端的请求,使用HTTP进行通信。

使用IDEA创建具有Maven依赖的Webapp方法

创建Servlet

Servlet是所有Web应用程序的核心类,它是唯一的既可以直接处理和响应用户请求,也可以将处理工作委托给应用中的其它部分的类。
除非某些过滤器提前终止了客户端的请求,否则所有的请求都将被发送到某些Servlet中。
所有的Servlet都实现了javax.servlet.Servlet接口,但通常不是直接实现的。Servlet只是一个简单接口,它包含了初始化并销毁Servlet和处理请求的方法。

多数情况下,Servlet都继承自javax.servlet.GenericServlet。GenericServlet仍然是一个不依赖于具体协议的Servlet,它只包含一个抽象的service方法,但它同时也包含了几个辅助方法用于日志操作和从应用和Servlet配置中获取信息。
作为响应HTTP请求的java.servlet.http.HttpServlet,它继承了GenericServlet,并实现了只接受HTTP请求的service方法。然后它提供了响应每种HTTP方法类型的方法的空实现。
我们之后的Servlet将总是继承HTTPServlet。它的方法接收的是javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse参数。
eg:

import javax.servlet.http.HttpServlet;

public class HelloServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest r,HttpServletResponse ,re) 
    throws ServletException,IOException{
        response.getWriter().println("Hello, World")
    }
}

以上,该Servlet即能够对GET请求做出响应,并在响应主体中显示出“Hello, World”。

初始化和销毁方法

@Override
public void init() throws ServletException{
    ...
}

@Override
public void destroy(){
    ...
}

在Web容器启动Servlet时,会调用Servlet的init方法,有时也会在部署应用程序时调用该方法。
在容器关闭Servlet时,会调用destroy方法。

配置可部署的Servlet

在web-INF目录中创建web.xml文件,并对Servlet进行配置,使它可以正确地部署到服务器中。

向描述符中添加Servlet

如在web.xml中添加部署描述:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">

    <display-name>Hello World Application</display-name>

示例中,<display-name></display-name>描述的为应用程序在应用服务器中显示的名字。<web-app></web-app>中version特性描述应用程序使用的Servlet API版本。
在该例中,init方法将在web应用程序启动后,第一个请求到达Servlet时调用,但是如果init需要花费过长时间来完成工作,则会导致第一个请求的时间被延长很多,因此我们可以在Servlet配置中进行调整,以让它在Web应用启动之后立即启动。

<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.wrox.HelloServlet</servlet-class>
    <load-on-start-up>1</load-on-start-up>
</servlet>

如上,在<load-on-start-up>标签中设置1,使得Web容器在应用程序启动之后,立即启动Servlet。如果多个Servlet配置都包含了该标签,它们的启动顺序将按照标签内的值的大小顺序启动,1表示第一个启动,数字越大表示启动越晚。如果出现值相同的情况,则按照它们出现在配置文件中的顺序来启动。
使用配置文件来告诉Servlet来应该对哪些请求URL做出响应:

<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/greeting</url-pattern>
</servlet-mapping>

使用如上配置之后,所有访问应用程序相对URL/greeting的请求都将由helloServlet处理。
Web容器通过这种方式关联两个配置。
Servlet类的service方***处理所有到达的请求。最终,它必须根据所使用的协议解析并处理到达请求中的数据,然后返回客户端可接受的响应。

了解doGet、doPost和其他方法

HttpServletRequest接口是对ServletRequest的扩展,它将提供关于收到请求的额外的与HTTP协议相关的信息。它指定了多个可以获得HTTP请求的详细信息的方法。它也允许设置请求特性。
HttpServletREquest最重要的功能:从客户端发送的请求中获取参数。
请求参数有两种不同的形式:查询参数(也成为URI参数)、以application/x-www-form-urlencoded或multipart/form-data编码的请求正文。所有的请求方法都支持查询参数,它们被添加在HTTP请求的第一行数据中,如:
GET /index.jsp?productId=123456789&category=Book HTTP/1.1
例子中包含两个查询参数:productId和category。
方法getParameter将返回参数的单个数值。如果参数有多个数值,getParameter将返回第一个值,而getParameterValues将返回参数的值的数组。如果参数只有一个值,则返回只有一个值的数组。方法getParameterMap将返回一个包含了所有参数名值对的java.util.Map<String,String[]>,而getParameterNames方法将返回所有可用参数的名字的枚举。
方法getInputStream将返回一个javax.servlet.ServletInputStream,而方法getReader将返回一个java.io.BufferedReader,它们都可用于读取请求内容。如果请求内容是基于字符编码的,使用BufferedReader是最简单的方式,请求数据是二进制的,必须使用ServletInputStream,这样才可以访问字节格式的请求内容。永远不应该在同一请求上同时使用这两种方法。

HttpServletResponse继承了ServletResponse接口,提供了对响应中与HTTP协议相关的属性的访问。可以使用响应对象完成设置响应头、编写响应正文、重定向请求、设置HTTP状态码以及将Cookies返回到客户端等任务。
方法getOutputStream返回一个javax.servletServletOutputStream,而方法getWriter将返回一个java.io.PrintWriter,通过对它们都可以向响应中输出数据。
我们可以在Servlet中重写doGet和doPost方法来分别处理get和post请求。
需要注意的是,我们应该在Servlet的声明上进行注解,如:

@WebServlet{
    name = "helloServlet",
    urlPatterns = {"/greeting","/wazzup"},
    loadOnStartup = 1
}
public class HelloServlet extends HttpServlet
{
...
}

如上所示,可以代替编写对用的XML。

<b>使用初始化参数配置应用程序</b>
虽然在Servlet类上的注解代替了在部署描述符文件中的Servlet声明和映射,但是存在其它的一些配置必须通过部署描述符才能完成。上下文初始化参数就是其中之一。在web.xml文件中使用<context-param》标签声明上下文初始化参数。

声明初始化参数举例:

<context-param>
    <param-name>setting</param-name>
    <param-value>value</param-value>
</context-param>

在Servlet代码的任何地方都能够轻松获得和使用初始化参数,使用代码举例:

ServletContext sc = this.getServletContext();
sc.getInitParameter("setting");

或者:
定义:

<servlet>
    <servlet-name>...</servlet-name>
    <servlet-class>...</servlet-class>
    <init-param>
        <param-name>setting</param-name>
        <param-value>hello</param-value>
    </init-param>
</servlet>

使用:

ServletConfig sc = this.getServletConfig();
sc.getInitParameter("setting");

Web应用程序是天然的多线程应用程序。Web容器中通常会包含某种类型的线程池,它们被称为连接池或执行池。当容器收到请求时,它将在池中寻找可用的线程。如果找不到可用的线程,并且线程池已经达到了最大线程数,那么该请求将被放入一个队列等待获得可用的线程。

#读书笔记##Java#
全部评论
老哥总结的很棒了
点赞 回复 分享
发布于 2018-08-13 02:06

相关推荐

10-05 23:02
东北大学 Java
我说句实话啊:那时候看三个月培训班视频,随便做个项目背点八股,都能说3 40w是侮辱价
点赞 评论 收藏
分享
牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
点赞 3 评论
分享
牛客网
牛客企业服务