Servlet - 基础

Servlet基础之实现第一个servlet程序 实现第一个Servlet程序1.     创建servlet文件在某个盘下创建一个新的文件夹,(文件夹名字自己开心就好,也可以是原来命名好的文件夹)在此目录下创建一个XXXX.java文件,内容如下packagejava_web;//这是包名,也就是你创建的文件夹的名字,从大到小,我是直接在D盘下创建的java_web的文件夹,所以包名就直接是java_webimportjava.io.*;imp... 阅读详情

本文转自:http://blog.youkuaiyun.com/zjf280441589/article/details/51247469


HTTP协议

HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器(Browser)和万维网服务器(WebServer)之间互相通信的规则.其主要特点可简单概括如下:
1) 简单快速: 客户端向服务器请求服务时,只需传送请求方法和路径, 因此使得HTTP服务器的程序规模小,通信速度快;
2) 灵活: HTTP允许传输任意类型的数据对象(传输类型由Content-Type控制);
3) 无连接: 无连接的含义是限制每次连接只处理一个请求;
4) 无状态: 无状态是指协议对于事务处理没有记忆能力(如果后续处理需要前面的信息,则必须重传.这样可能导致每次连接传送的数据量增大.但如果在服务器不需要先前信息时它的应答就会非常快快).


HTTP请求

一个HTTP请求通常包含三部分(中间已空行隔开):

请求行:        (方法 /统一资源标识符URI/协议/版本)
请求头:        (Accept/Accept-Language等)
空行:     (CRLF)
请求体:        (携带的数据信息, GET请求没有)

HTTP请求可以使用HTTP标准中定义的所有请求类型, HTTP1.1支持7种请求类型, 但在互联网应用中最为常用的只有GET与POST.


HTTP-GET
GET /WeChat/cc3200/get_status.do HTTP/1.1
Host: aliyun
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
  • 请求头解析
请求头描述
User-Agent浏览器与操作系统信息
Accept当前浏览器可以接收的文档类型
Accept-Language当前浏览器支持的语言
Accept-Encoding当前浏览器支持的压缩格式:服务器会把数据压缩后再发送到网络中传输
Accept-Charset当前浏览器支持的编码
Connection当前浏览器支持的连接方式(keep-alive即保持一段时间的连接,默认为3000ms)
Cookie如果不是第一次访问该网址,可能会在请求中把上次服务器响应的Cookie数据一并发送过去

HTTP-POST
POST /WeChat/cc3200/get_status.do HTTP/1.1
Content-Length: 36
Cache-Control: max-age=0
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8080/test/
...

user_name=feiqing&user_password=pass
  • 请求头解析
请求头描述
Referer表明请求来自哪个页面
Content-Typeapplication/x-www-form-urlencoded:表单数据类型,说明会使用URL编码来格式化数据
Content-Length请求体长度
user_name=feiqing&user_password=pass请求体: 请求携带的数据

HTTP响应

一个HTTP响应通常也包含三部分(中间已空行隔开):

响应行:        (协议/状态码/描述)
响应头:        (Server/Content-Length/Set-Cookie等)
空行:     (CRLF)
响应体:        (携带的数据)

HTTP响应是由服务器发送给浏览器的数据,浏览器会根据HTTP响应来解析并显示内容:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 8
Date: Sun, 17 Apr 2016 12:39:11 GMT

<html>
    ...
</html>
  • 响应头解析
响应头描述
Server服务器信息
Content-Length响应实体长度
Set-Cookie响应给客户端的Cookie
Expires: -1; / Cache-Control: no-cache; / Pragma: no-cache;设置浏览器不要缓存数据
Refresh自动刷新页面

在HTML文件中可用<meta/>标签来设置响应头信息:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 
  • 1
  • 1

响应状态码

状态码说明了响应的真正含义:

状态描述
200请求成功
404请求资源没找到
500服务器内部错误
302重定向: 表示服务器要求浏览器重新再发一个请求到服务器指定的一个Location
304缓存未过期(服务器资源未曾修改), 详细可参考理解HTTP/304响应

Tomcat

Tomcat是一个免费开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成. 由于有了Sun的参与和支持, 因此最新的Servlet和Jsp规范总能在Tomcat中得到体现.主页:http://tomcat.apache.org/.


Tomcat目录结构

  • bin: 存放可执行脚本文件(如startup.bat/startup.sh等)
  • conf: 存放Tomcat相关配置文件:
    • server.xml: 整个Tomcat运行环境配置(如端口号/虚拟主机等)
    • web.xml: 部署描述符文件(定义了默认JSP/Servlet处理规则,是所有web项目中WEB-INF/web.xml的父文件)
    • context.xml: 对所有应用的统一配置.
  • lib:Tomcat类库, 该目录中的jar包所有项目共享.
  • logs : Tomcat日志目录.
  • webapps:存放WEB应用,其每个子目录都是一个项目;
  • work:运行时生成的文件.

server.xml

<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>
  • 元素解析
元素描述
<Server/>根元素,整个Tomcat的配置信息
<Service/>服务(在<Server/>中只能有一个<Service/>)
<Connector/>连接
<Engine/>引擎,是<Service/>组件核心
<Host/>每个<Host/>元素表示一台虚拟主机.每台虚拟主机都有自己的主机名和项目目录
<Context/>每个<Context/>元素表示一个应用.如果应用在<Host/>的appBase指定的目录下,那么可以不配置<Context/>元素,如果是外部应用,那么就必须配置<Context/>

Tomcat配置

1. 配置端口号

编辑%CATALANA_HOME%\conf\server.xml文件中的<Connector/>元素

<!-- A "Connector" represents an endpoint by which requests are received
     and responses are returned. Documentation at :
     Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
     Java AJP  Connector: /docs/config/ajp.html
     APR (HTTP/AJP) Connector: /docs/apr.html
     Define a non-SSL HTTP/1.1 Connector on port 8080
-->
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />
2. 配置外部应用

配置外部应用之后, 项目就可以不用拷贝到webapps目录下,自定义项目存放位置,其配置方式有两种:

  • 1: 修改server.xml
    在<Host/>元素中添加<Context/>元素
  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">
    <Context path="/test/" docBase="/home/www/test"/>

    <!-- Access log processes all example.
         Documentation at: /docs/config/valve.html
         Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />

  </Host>

如果指定path为空(path=”“), 则默认访问的项目就是/home/www/test, 而不再是webapps下的ROOT.

  • 2: 编辑conf/catalana/localhost目录:
    新增test.xml文件
<Context docBase="/home/www/test"/>
 
  • 1
  • 1

存放到%CATALANA_HOME%/conf/catalana/localhost目录下, 文件名即为应用名.


Servlet

Servlet技术核心就是Servlet接口,所有Servlet实现类都必须实现Servlet接口,Servlet容器(如Tomcat)会把Servlet类加载到内存并生成唯一实例,当有请求到来时调用其方法.

  • 实现Servlet方式有三种:
    1. 实现javax.servlet.Servlet接口
    2. 继承javax.servlet.GenericServlet类
    3. 继承javax.servlet.http.HttpServlet类

Servlet

Servlet接口定义如下

public interface Servlet {

    public void init(ServletConfig config) throws ServletException;

    public ServletConfig getServletConfig();

    public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;

    public String getServletInfo();

    public void destroy();
}

方法描述
init在第一次请求该Servlet(默认)或容器启动时, Servlet容器就会调用init(), 且只调用一次
service每次请求Servlet都会调用该方法
destroy销毁Servlet时(卸载应用/关闭容器时), 调用该方法
  • HelloServlet
/**
 * @author jifang.
 * @since 2016/4/17 8:32.
 */
public class HelloServlet implements Servlet {

    private ServletConfig config;

    public void init(ServletConfig config) throws ServletException {
        System.out.println("init()...");
        this.config = config;
        System.out.println("config: <" + config + ">");
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service()...");
        System.out.println("req: <" + req + ">, res: <" + res + ">");
        res.getWriter().print("<h1>HelloServlet</h1>");
    }

    public void destroy() {
        System.out.println("destroy()...");
    }


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

    public String getServletInfo() {
        return null;
    }
}

  • web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0"
         metadata-complete="true">
    <display-name>JavaWeb</display-name>
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello_servlet.do</url-pattern>
    </servlet-mapping>
</web-app>

  1. url-pattern
    <url-pattern/>用来指定Servlet的访问路径,必须以/开头.

    • 可以在<servlet-mapping/>配置多个<url-pattern/>, 此时一个Servlet实例就绑定多个URL.
    • 可以在<url-pattern/>中使用通配符*,可以使一个Servlet绑定一组URL, 但*不能出现在中间位置,也不能只有*通配符, 另外, 通配符只是一种模糊匹配URL的方式,如果存在更具体的<url-pattern/>,那么会优先选择精确匹配.
  2. 配置在容器启动时创建Servlet实例

<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<load-on-startup/>元素可以让容器在启动时就创建该Servlet实例(调用init()方法),注意<load-on-startup/>元素的值必须是>=0的整数,它代表容器启动时创建Servlet实例的顺序.


GenericService

GenericService抽象类实现了Servlet接口并完成以下工作:
1. 将init()方法中的ServletConfig赋给一个实例变量, 使他可以通过getServletConfig()来获取.
2. 为Servlet接口的所有方法提供默认实现.
3. 提供方法来包装ServletConfig.

  • Generic部分代码
public abstract class GenericServlet 
    implements Servlet, ServletConfig, java.io.Serializable
{
    private transient ServletConfig config;

    public GenericServlet() { }

    public void destroy() {
    }

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

        return sc.getInitParameter(name);
    }

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

        return sc.getInitParameterNames();
    }   


    public ServletConfig getServletConfig() {
    return config;
    }

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

        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 abstract void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;

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

        return sc.getServletName();
    }
}

HttpServlet

HttpServlet是GenericServlet的子类,它提供了对HTTP协议的支持.覆盖了GenericServlet的service()方法,并新增了接受HttpServletRequest/HttpServletResponse参数的service()方法:

@Override
public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException
{
    HttpServletRequest  request;
    HttpServletResponse response;

    if (!(req instanceof HttpServletRequest &&
            res instanceof HttpServletResponse)) {
        throw new ServletException("non-HTTP request or response");
    }

    request = (HttpServletRequest) req;
    response = (HttpServletResponse) res;

    service(request, response);
}


protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
{
    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            // servlet doesn't support if-modified-since, no reason
            // to go through further expensive logic
            doGet(req, resp);
        } else {
            long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
            if (ifModifiedSince < lastModified) {
                // If the servlet mod time is later, call doGet()
                // Round down to the nearest second for a proper compare
                // A ifModifiedSince of -1 will always be less
                maybeSetLastModified(resp, lastModified);
                doGet(req, resp);
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
        }

    } else if (method.equals(METHOD_HEAD)) {
        long lastModified = getLastModified(req);
        maybeSetLastModified(resp, lastModified);
        doHead(req, resp);

    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);

        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    }
}
  • 原始的service()将请求/响应向下转型为HttpServletRequest/HttpServletResponse, 并调用新的service(). 由于HttpServlet在新的service()方法中已经做了很多工作, 因此在继承HttpServlet实现自动以Servlet时, 则只需覆盖doGet()/doPost()等即可, 而没有必要覆盖service()(极少数情况需要覆盖doHead()等)

注意: Request/Response向下转型总会成功:因为在调用service()方法时,Servlet容器总会预计使用HTTP,从而直接创建并传递HttpServletRequest/HttpServletResponse实例.

  • HelloHttpServlet
/**
 * @author jifang.
 * @since 2016/4/20 19:48.
 */
@WebServlet(name = "HelloHttpServlet", urlPatterns = "/hello_http_servlet.do")
public class HelloHttpServlet extends HttpServlet {

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

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet() ...");
    }
}

HttpServletRequest

对于每一个HTTP请求, Servlet容器会在调用service()方法时创建Request实例并传递给service形参,HttpServletRequest是Request在HTTP环境下的实例,其封装了有关请求的信息:

  • 封装请求头信息;
  • 封装请求正文数据(GET没有正文);
  • 提供请求转发/包含功能;
  • 作为域对象, 可以传递数据.

获取请求头
方法描述
String getHeader(String name)Returns the value of the specified request header as a String.
Enumeration<String> getHeaderNames()Returns an enumeration of all the header names this request contains.
long getDateHeader(String name)Returns the value of the specified request header as a long value that represents a Date object.
Enumeration<String> getHeaders(String name)Returns all the values of the specified request header as an Enumeration of String objects.
int getIntHeader(String name)Returns the value of the specified request header as an int.
String getRemoteAddr()Returns the Internet Protocol (IP) address of the client or last proxy that sent the request.
String getMethod()Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
String getContextPath()Returns the portion of the request URI that indicates the context of the request.
  • 获取请求来源
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String referer = request.getHeader("Referer");
    String userAgent = request.getHeader("User-Agent");
    composeResponse(referer, userAgent, response);
}

private void composeResponse(String referer, String userAgent, HttpServletResponse response) throws IOException {
    response.setHeader("Content-Type", "text/html;charset=utf-8");
    PrintWriter writer = response.getWriter();
    if (!Strings.isNullOrEmpty(referer)) {
        writer.print("<h1>来源地址: " + referer + "</h1>");
    } else {
        writer.print("<h1>来自浏览器地址栏</h1>");
    }

    writer.print("<hr>");
    writer.print("<h1>来源信息: " + userAgent + "</h1>");
}

获取请求参数
方法描述
String getParameter(String name)Returns the value of a request parameter as a String, or null if the parameter does not exist.
Map<String,String[]> getParameterMap()Returns a java.util.Map of the parameters of this request.
Enumeration<String> getParameterNames()Returns an Enumeration of String objects containing the names of the parameters contained in this request.
String[] getParameterValues(String name)Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does not exist.
  • 获取微信请求消息
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Element root;
    String xml = request.getParameter("xml");
    try {
        if (!Strings.isNullOrEmpty(xml)) {
            root = new SAXReader().read(new StringReader(xml)).getRootElement();
        } else {
            String data = CharStreams.toString(new InputStreamReader(request.getInputStream()));
            root = new SAXReader().read(new StringReader(data)).getRootElement();
        }
    } catch (DocumentException | IOException e) {
        LOGGER.error("parse wx xml error", e);
        throw new RuntimeException();
    }

    // ...
}

请求转发/包含

Request提供了getRequestDispatcher()来获取一个RequestDispatcher, 并由其提供请求转发/请求包含功能.

Request方法描述
RequestDispatcher getRequestDispatcher(String path)Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.

请求转发/请求包含都是由多个Servlet协作完成一个请求, 因此需要从一个Servlet中跳到另一个Servlet中:

RequestDispatcher方法描述
void include(ServletRequest request, ServletResponse response)Includes the content of a resource (servlet, JSP page, HTML file) in the response.
void forward(ServletRequest request, ServletResponse response)Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server.
  • 请求转发: 原Servlet只会保留设置的响应头信息.
  • 请求包含: 原Servlet既会保留响应头, 还会保留响应体内容.

注意: 请求转发时, 可能会因为原Servlet设置了过多的响应体内容导致抛出异常java.lang.IllegalStateException: Cannot forward after response has been committed


域对象传递数据

由于请求转发/请求包含都只是一次请求, 因此在多个Servlet之间都是共用一个Reqeust, 因此可以利用Request的在多个Servlet之间共享数据:

方法描述
Object getAttribute(String name)Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
Enumeration<String> getAttributeNames()Returns an Enumeration containing the names of the attributes available to this request.
void setAttribute(String name, Object o)Stores an attribute in this request.
void removeAttribute(String name)Removes an attribute from this request.

HttpServletResponse

同Request, Servlet容器会在每次调用service()方法时创建Response实例并传递给service()形参,HttpServletResponse是Response绑定在HTTP环境下的实例, 其隐藏了将响应发送给浏览器的复杂性:

  • 设置响应状态码;
  • 设置响应头信息;
  • 设置响应正文;

设置响应状态码
方法描述
void setStatus(int sc)Sets the status code for this response.
void sendError(int sc)Sends an error response to the client using the specified status code and clears the buffer.
void sendError(int sc, String msg)Sends an error response to the client using the specified status and clears the buffer.

关于状态码的描述, 详见HTTP协议部分介绍, 在此就不再赘述.

  • 响应404
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // response.sendError(404, "nothing!!");
    response.setStatus(404);
}

设置响应头信息
方法描述
void setHeader(String name, String value)Sets a response header with the given name and value.
void addHeader(String name, String value)Adds a response header with the given name and value.
void setIntHeader(String name, int value)Sets a response header with the given name and integer value.
void addIntHeader(String name, int value)Adds a response header with the given name and integer value.
void addDateHeader(String name, long date)Adds a response header with the given name and date-value.
void setDateHeader(String name, long date)Sets a response header with the given name and date-value.
void sendRedirect(String location)Sends a temporary redirect response to the client using the specified redirect location URL and clears the buffer.

关于HTTP响应头的描述, 详见HTTP协议部分介绍, 在此就不再赘述.

  • 设置禁用浏览器缓存(Cache-Control, pragma, expires)
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("pragma", "no-cache");
    response.setDateHeader("expires", -1);
}
  • 设置重定向(302, Location)
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
    response.setHeader("Location", "http://www.baidu.com");
}

HttpServletResponse还提供了另外一种重定向的方式, 直接使用sendRedirect()方法, 避免了以上的步骤:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.sendRedirect("http://www.baidu.com");
}

设置响应正文

Response提供了如下两个方法来获取输出流对象以响应HTTP正文内容

方法描述
ServletOutputStream getOutputStream()Returns a ServletOutputStream suitable for writing binary data in the response.
PrintWriter getWriter()Returns a PrintWriter object that can send character text to the client.

OutputStream传输二进制数据流(字节数据), 常用作文件下载; Writer传输字符数据, 常用作响应HTTP正文内容(如HTML/XML等).

注意: 在一个请求中,不能同时使用这两个流, 否则会抛出IllegalStateException.

字符响应流
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter writer = response.getWriter();
    writer.print("<html>");
    writer.print("<h1>content</h1>");
    writer.print("</html>");
}
  • 缓冲区
    PrintWriter的默认缓冲区大小为8K, 因此当响应数据大小<8K时, 数据存放在缓冲区, 而不会立刻发送到浏览器, 直到Servlet执行结束,因此如果希望马上发送给浏览器, 需要调用Response的flushBuffer()方法手动刷新缓冲区.

ServletConfig

在容器初始化Servlet时, 会将一个ServletConfig实例传给init()方法,其封装了@WebServlet/部署描述符传递给Servlet的配置信息:

方法描述
String getInitParameter(String name)Gets the value of the initialization parameter with the given name.
Enumeration<String> getInitParameterNames()Returns the names of the servlet’s initialization parameters as an Enumeration of String objects.
ServletContext getServletContext()Returns a reference to the ServletContext in which the caller is executing.
  • java
public void init(ServletConfig config) throws ServletException {
    this.config = config;

    Enumeration<String> names = config.getInitParameterNames();
    while (names.hasMoreElements()) {
        String name = names.nextElement();
        String value = config.getInitParameter(name);

        System.out.println(name + " -> " + value);
    }
}
  • web.xml
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class>
        <init-param>
            <param-name>admin</param-name>
            <param-value>com.fq</param-value>
        </init-param>
        <init-param>
            <param-name>e-mail</param-name>
            <param-value>zhujifang666@163.com</param-value>
        </init-param>
    </servlet>

ServletContext

ServletConfig中提供了获取ServletContext的方法getServletContext(),ServletContext代表Servlet应用程序,且每个应用程序仅有一个ServletContext实例,其在容器启动时创建, 在容器关闭时销毁, 因此可以利用其在多个Servlet中传递数据.
所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:

方法描述
void setAttribute(String name, Object object)Binds an object to a given attribute name in this ServletContext.
Object getAttribute(String name)Returns the servlet container attribute with the given name, or null if there is no attribute by that name.
Enumeration<String> getAttributeNames()Returns an Enumeration containing the attribute names available within this ServletContext.
void removeAttribute(String name)Removes the attribute with the given name from this ServletContext.

应用初始化参数

前面看到ServletConfig可以获取针对本Servlet的初始化参数,而利用ServletContext可以获取针对本应用程序的公共初始化参数:

方法描述
String getInitParameter(String name)Returns a String containing the value of the named context-wide initialization parameter, or null if the parameter does not exist.
Enumeration<String> getInitParameterNames()Returns the names of the context’s initialization parameters as an Enumeration of String objects, or an empty Enumeration if the context has no initialization parameters.
  • web.xml
<context-param>
    <param-name>admin</param-name>
    <param-value>feiqing</param-value>
</context-param>
<context-param>
    <param-name>e-mail</param-name>
    <param-value>zhujifang666@163.com</param-value>
</context-param>

  • java
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletContext context = getServletContext();
    String admin = context.getInitParameter("admin");
    String email = context.getInitParameter("e-mail");
    System.out.printf("admin: %s%n", admin);
    System.out.printf("e-mail: %s%n", email);
}


获取资源

可以使用ServletContext来获取Web应用下的资源路径/资源流等内容:

方法描述
String getRealPath(String path)Gets the real path corresponding to the given virtual path.
URL getResource(String path)Returns a URL to the resource that is mapped to the given path.
InputStream getResourceAsStream(String path)`Returns the resource located at the named path as an InputStream object.
Set<String> getResourcePaths(String path)Returns a directory-like listing of all the paths to resources within the web application whose longest sub-path matches the supplied path argument.
Servlet(一)Servlet基础 Servlet基础 目录 Servlet基础 -Servlet概述 -Tomcat容器等级 -HelloServlet手工编写第一个Servlet -HelloServlet使用eclipse编写第一个Servlet -Servlet执行流程 -Tomacat装载Servlet的三种情况 -JSP与SerVlet对象的对应关系 -通过Servlet获取表单数据 -Servle... 阅读详情

相关推荐

【智驾与大模型】端到端与多模态大模型的精彩之旅

智驾和大模型的回顾与展望。开头的笔者自述也说了些心窝子话,边缘计算的监管刻不容缓!

仿生实验室:从0到1,制作人脸表情交互机器人,记录过程,软硬件全部开源,与君共襄盛举! 1318

【Tomcat】各个版本Tomcat统一简单介绍,安装启动以及与原理简单介绍

作为一个Javaweb学习的小白,每天都在使用Tomcat,这可能是我唯一熟悉的服务器,但却对它不甚了解,真是罪孽深重,今天就来整理一下关于Tomcat服务器的相关知识,加深并巩固对它的学习与理解。首先呢,我们先来看看它的基础知识与基本使用方法;紧接着我们会一起来看看怎么处理一些遇到的服务器报错问题;最后,我们一起来学习一下它的原理与并看看它的源码。一,Tomcat的自我介绍    Tomcat是...

SuperMan程序人生(关注微信公众号) 3701

树莓派CM4 PCIe扩展方案与ASM1184e芯片应用

PCIe(Peripheral Component Interconnect Express)是计算机硬件中重要的高速串行总线标准,广泛应用于存储、网络等设备连接。其核心原理是通过差分信号实现高带宽传输,PCIe Gen2 x1的理论带宽可达5Gbps。在嵌入式开发中,PCIe扩展技术能有效解决单板计算机接口不足的问题,特别适合树莓派等微型平台。ASMedia ASM1184e作为PCIe交换芯片,可将单个接口扩展为多个,支持热插拔且免驱动,极大提升了工程灵活性。通过PCIe交换机方案,开发者能在树莓派CM

weixin_42602368的博客 421

Servlet 循环输出不同字体大小的文本

package groop.com; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Htt

qq_36122443的博客 1573

UE4初学笔记_02_编辑器界面

不同版本可能不一样,这里是4.25 UE4编辑器主界面(也称为关卡编辑器)主要用于构建世界场景和关卡以及放置资源。 1.菜单栏 2.关卡编辑器(Level Editor)工具栏 3.“模式”(Modes)面板 4.“内容浏览器”(Content Browser)面板 5.“视口”(Viewport)面板 6.“世界大纲视图”(World Outliner)面板 7.“细节”(Details)面板 1.菜单栏 菜单栏包含“文件”(File) 、“编辑”(Edit) 、“窗口”(Win.

来自火星的猫 3092

【SAP-MDG】工作流任务配置实战:从基础配置到代理分配详解

本文详细解析了SAP MDG工作流任务配置的全流程,从基础配置到代理分配的关键操作。通过实战案例和最佳实践,帮助用户掌握Configure Workflow Tasks的核心技巧,包括环境检查、代理分配、SWDD事务码使用及常见问题排查,提升主数据管理效率。

weixin_33738555的博客 248

servlet基础总结

什么是servlet Servlet(Server Applet)是Java Servlet的简称,是小服务程序或服务连接器,是用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容. 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。 第一个servle...

少说,多做。 4426

AEJoy —— 表达式之仅限在某一维摆动【JS】

效果图 wiggle() 的作用仅限于水平方向 想法 wiggle() 确实是一个非常方便的工具,但有时您希望对它有更多的控制。在本例中,我们希望仅将摆动限制在水平方向。 设计 要理解 wiggle() 最重要的一点是,它生成的结果与应用它的属性具有相同的维度。例如,如果你将 wiggle() 应用于 3D 层的 position 属性,结果将是一个由三个元素组成的数组(x、y 和 z 各一个)。我们需要做的就是将 wiggle() 的结果捕捉到一个变量(我们称之为 “w” ),然后从这个变量中提取我们想

ShaderJoy 的兴趣技术杂货铺 2094

Servlet基础详解

Servlet的基本概念及使用规范

m0_57789266的博客 2万+

【图像去噪】论文精读:AKDT: Adaptive Kernel Dilation Transformer for Effective Image Denoising

论文题目:AKDT: Adaptive Kernel Dilation Transformer for Effective Image Denoising —— AKDT:用于有效图像去噪的自适应核膨胀Transformer图像去噪是一项基本但具有挑战性的任务,特别是在处理高分辨率图像和复杂的噪声模式时。大多数现有方法依赖于标准的 Transformer 架构,该架构通常计算复杂度高,并且对不同噪声水平的适应性有限。在本文中,我们介绍了自适应核膨胀Transformer(AKDT)

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 1044

在RV1126上实现人脸识别----MobileFaceNet转成rknn模型

目录 1.模型下载 2 转成rknn模型并推理 3 查看网络模型 1.模型下载 首先下载MobileFaceNet的模型,github下载地址为:https://github.com/sirius-ai/MobileFaceNet_TF/tree/master/arch/pretrained_model/ 2 转成rknn模型并推理 import numpy as np import cv2 from rknn.api import RKNN if __name__ == '__..

C/C++、嵌入式开发、深度学习算法、模型部署与推理优化 3526

Servlet 基础

简述 Servlet是用Java语言编写应用到Web服务器端的扩展技术,他先于JSP产生,可以方便地对Web应用中的HTTP请求进行处理。在JavaWeb程序开发中,Servlet主要用于处理各种业务逻辑,它比JSP更具有业务逻辑层的意义,而且Servlet在安全性,扩展性以及性能方面都十分优秀,它在JavaWeb程序开发以及MVC狂叫地应用方面起到了极其重要的作用。 结构体系 HttpServlet类继承GenericServlet类,GennericServlet类继承三个接口,分别是Servlet接口

一夜星尘 1万+

【python数据挖掘课程】二十八.基于LDA和pyLDAvis的主题挖掘及可视化分析

这是《Python数据挖掘课程》系列文章,前面很多文章都讲解了数据挖掘、机器学习,这篇文章主要讲解LDA和pyLDAvis算法,同时讲解如何读取CSV文本内容进行主题挖掘及可视化展示。文章比较基础,希望对你有所帮助,提供些思路,也是自己教学的内容。推荐大家购买作者新书《Python网络数据爬取及分析从入门到精通(分析篇)》,如果文章中存在错误或不足之处,还请海涵。 目录: 一.显示结果及安装 二.LDA主题挖掘 三.pyLDAvis可视化分析 四.小结

杨秀璋的专栏 1万+

Servlet基础

本质:Servlet 是运行在==服务器端的 Java 类==,是用java语言编写的他是由服务器端(如 Tomcat)管理生命周期(创建、初始化、处理请求、销毁)的(一句话:是==Tomcat解析和执行==)他是按照Servlet规范开发的(只有遵循这个规范,除了tomcat,像Servlet weblogic也可以执行)(像jdbc一样,本质是一套规范一个接口,只要你遵循它的规范就可以跟它对接功能强大,可以完成几乎所有的网站功能(在以前老程员,使用Servlet开发网站) 技术栈要求高。

2402_83364789的博客 677

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【Servlet基础】Servlet项目创建

Tomcat在调用doGet的时候,Tomcat就会解析这次的HTTP请求,生成一个HttpServletRequest对象,这个对象的属性啥的都是和HTTP协议格式匹配的,相当于Tomcat帮我们把HTTP请求解析好了,同时Tomcat也会构造出一个空的HttpServletResponse对象(此处的空对象不是null,而是一个new好但是没有初始化属性的对象),把这个resp对象也会传递到doGet里面。这里的1和3都是Tomcat帮我们实现的,我们写代码只关心2,也就是doGet要完成的工作。

m0_62241955的博客 1621

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

servlet基础_Servlet基础

servlet基础 通过本教程,我将尝试使您更接近Java Servlet模型。 在检查servlet规范中定义的类之前,我将解释在开始开发Web应用程序之前需要了解的基本知识。 了解Java Servlet模型 首先,不仅为基于请求和响应编程模型的规范的Web应用程序定义Java Servlet模型。 但基本上,它最常用于与HTTP协议交互,因此从现在开始,我们将不再在HTTP应用程...

最佳 Java 编程 141

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【Servlet 基础】Servlet项目的创建

Servlet是一种实现动态页面的技术,所谓动态页面就是用户不同,时间不同,输入的参数不同,页面内容也不会发生变化,而静态页面是内容始终固定不变的,html就是静态的资源文件 Servlet为不同的JavaWeb服务器规定了响应的编程规范,它屏蔽Web服务器实现的细节(不同的服务器对请求的解析和响应的封装可以是不同的),但是定义好了统一的编程规范(统一的类,接口,方法),也就是换一个Web服务器,还可以使用

书生-w的博客 1万+

【java】Servlet基础

【java】Servlet基础1. Servlet 是什么?2. Servlet 架构3. Servlet的主要任务4. Servlet快速入门:5. IDEA与tomcat的相关配置 1. Servlet 是什么? Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层...

来日浅谈的博客 716

【Servlet】Servlet学习之基础篇

由浅入深的Servlet系列文章(一)Servlet基础

m0_52410356的博客 402

【Servlet 基础】

【Servlet 基础】

Jade_Heng_Star的博客 334

Servlet的基础

Servletr入门 Servlet : server applet(服务器小程序) 概念 : 运行在服务器端的小程序 Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。自己定义一个类,来实现Servlet接口,复写方法。 步骤: 创建JavaEE项目 定义一个类,实现servlet接口 public class ServletDemo1 implements Servlet 实现接口中的抽象方法 配置servlet 在web.xml中 &

小马Mark的博客 139

servlet基础实验

实 验 报 告 实验名称 Servlet基础 日期 2020年 10 月20 日 一、实验目的: 1、理解Servlet的工作原理; 2、掌握javabean在web程序中的应用; 3、掌握基于Servlet的MVC模式; 二、实验环境: Eclipse 三、实验内容: 1、参考教材P142的例子,使用JSP、Servlet、JavaBean实现基于MVC模式的用户登录验证程序。 2、完成上述实验的基础上可以加入图片验证码

MrLuo8的博客 2655
上一篇: JVM初探- 内存分配、GC原理与垃圾收集器
下一篇: ABAP 开发系列(08): SAP Open SQL
Footloose_
博客等级 码龄10年 254粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值