Servlet基础

本文介绍了Java Servlet的基础知识,包括Servlet的概念、架构、任务,以及Tomcat服务器的使用。详细讲解了Servlet的生命周期,从创建到销毁的过程,并探讨了Servlet在实际应用中的部署和项目结构。此外,还涵盖了Servlet的编写,如处理GET/POST请求,读取表单数据,设置HTTP响应头部,使用过滤器和异常处理,以及Cookie和Session的管理。内容全面,适合初学者入门学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考教程:菜鸟教程

目录

Servlet基础概念

Servlet

Servlet 架构

Servlet 任务

Tomcat

导入jar包

Servlet 生命周期

Servlet部署/IDEA创建Web项目

JSP与HTML与Servlet

Servlet项目包结构

Servlet 实例

Servlet编写

Servlet与Get/Post

读取表单数据

Http获取请求头部信息

Http设置响应头部信息

Http设置头部状态码

过滤器Filter

异常处理

Cookie处理

Session会话

访问数据库

网页重定向

网页访问量计数器

Servlet 自动刷新页面


Servlet基础概念

Servlet

Java Servlet 是运行在 Web 服务器或应用服务器上的程序(注意,Servlet是这样一类程序的总称),它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

使用 Servlet可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

Java Servlet 是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。

Servlet 可以使用 javax.servlet 和 javax.servlet.http 包创建,它是 Java 企业版的标准组成部分,Java 企业版是支持大型开发项目的 Java 类库的扩展版本,这些类实现 Java Servlet 和 JSP 规范

Servlet 架构

Servlet æ¶æ

Servlet 任务

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

Tomcat

Apache Tomcat 是一款实现 Java Servlet 和 JavaServer Pages 技术的开源软件,可以作为测试 Servlet 的独立服务器,而且可以集成到 Apache Web 服务器。

下载完Tomcat之后,进入目录

\bin\startup.bat   执行脚本启动服务器
\bin\shutdown.bat     关闭服务器

导入jar包

通常需要手动在项目中导入apache-tomcat\lib\servlet-api.jar以使用javax.servlet.*

如果使用Maven等工具创建项目,需要在pom.xml(配置文件)中手动添加依赖

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

Servlet 生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。

  • Servlet 通过调用 init () 方法进行初始化。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 通过调用 destroy() 方法终止(结束)。
  • 最后,由 JVM 的垃圾回收器进行垃圾回收。

init() 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。

service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以不用对 service() 方法做任何动作,只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。

destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法让的Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。

Servlet çå½å¨æ

 在这里,Servlet是一个统称,表明是服务 HTTP 请求并实现 javax.servlet.Servlet 接口的 Java 类。Web 应用程序开发人员通常编写 Servlet 来扩展 javax.servlet.http.HttpServlet,并实现 Servlet 接口的抽象类专门用来处理 HTTP 请求。

Servlet部署/IDEA创建Web项目

默认情况下,Servlet 应用程序位于路径 <Tomcat-installation-directory>/webapps/ROOT 下,且类文件放在 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中。

并要对<Tomcat-installation-directory>/webapps/ROOT/WEB-INF/ 的 web.xml 文件进行相应的配置。这种修改很麻烦,通常创建Web项目更方便。

使用IDEA+maven创建Web项目,IDEA要使用企业版,否则无法开发web项目

贴一片教程:|---传送门---|,这教程虽然很啰嗦,但大体上差不多

JSP与HTML与Servlet

简单的说jsp是Servlet的简化版,html的复杂版,一般来说,Servlet用于处理数据,用在控制层,jsp用在视图层。

参考:魔法门传送

Servlet项目包结构

涉及到 WEB-INF 子目录的 Web 应用程序结构是所有的 Java web 应用程序的标准,并由 Servlet API 规范指定。给定一个顶级目录名 myapp,目录结构如下所示:

/myapp
    /images
    /WEB-INF
        /classes
        /lib

WEB-INF 子目录中包含应用程序的部署描述符,名为 web.xml。所有的 HTML 文件都位于顶级目录 myapp 下。

WEB-INF/classes 目录包含了所有的 Servlet 类和其他类文件,类文件所在的目录结构与他们的包名称匹配。例如,如果有一个完全合格的类名称 com.myorg.MyServlet,那么这个 Servlet 类必须位于以下目录中:

/myapp/WEB-INF/classes/com/myorg/MyServlet.class

Servlet 实例

package study;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 扩展HttpServlet,位于apache-tomcat/lib/下的servlet-api.jar里
 */

public class HelloWorld extends HttpServlet {
    private String message;

    @Override
    public void init() throws SecurityException{
        message="Hello World";
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");//设置响应报文格式
        PrintWriter out=response.getWriter();//获取写入流
        out.println("<h1>"+message+"</h1>");//将浏览器作为终端进行标准打印
    }

    public void  destory(){

    }
}

然后需要在webapp/WEB_INF/下的web.xml进行相应配置

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<!--web的响应控制都要在web.xml中进行相关的配置-->
<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--设置servlet,name代表ID,class为对应的类,mapping表示映射,由ID映射对应的所访问的url路径-->
  <!--url-pattern-name-class-->
  <servlet>
    <servlet-name>HelloWorld</servlet-name>
    <servlet-class>study.HelloWorld</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloWorld</servlet-name>
    <url-pattern>/HelloWorld</url-pattern>
  </servlet-mapping>


</web-app>

由以上过程我们可以看到,每一个页面对应一个Servlet,是一个对HttpServlet进行了相应扩展的class,也就是我们自己写的Servlet,在Servlet里定义一系列行为,最基本的包括init():初始化;service:重写doGet()/doPost()等由request设置对应的response;destory():断开连接后的工作,写好Servlet,要在web.xml下进行相应的配置,每一个class有对应的name,每一个name要对应相应的url-pattern,也就是访问页面时的url。

Servlet编写

Servlet与Get/Post

前端页面与服务器交互响应通过一些定义好的方法进行说明,如get/post等。

GET 方法向页面请求发送已编码的用户信息。页面和已编码的信息中间用 ? 字符分隔,如下所示:

http://www.test.com/hello?key1=value1&key2=value2

GET 方法是默认的从浏览器向 Web 服务器传递信息的方法,它会产生一个很长的字符串,出现在浏览器的地址栏中。

POST方法也是向服务器传输数据,但是是作为单独的消息发送,与Get功能一样

servlet通过doGet()方法处理get请求,doPost()方法处理post()请求

可以调用 request.getParameter() 方法来获取表单参数的值。

中间Servlet:

package study;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 响应Get方法,request通过get传递参数值,由getParameter()方法获取表单参数值,并进行解析返回response
 */
@WebServlet("/HelloForm")
public class HelloForm extends HttpServlet {
    private static final long serialVersionUID=1L;//序列化ID
    private static Map<String,String> storge=new HashMap<>();

    public HelloForm(){
        super();
        storge.put("1","LSL-test");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        response.setContentType("text/html;charset=UTF-8");
        String id=request.getParameter("id");//由getParameter()方法获取表单参数值

        PrintWriter out=response.getWriter();
        out.println("" +
                "<html>" +
                "    <head>" +
                "        <title>使用Get由id获取name</title>" +
                "    </head>" +
                "    <body>" +
                "        id="+id+
                "        name="+storge.get(id) +
                "    </body>" +
                "</html>");
    }
}

前端简单页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>lsl-使用Get由id获取name</title>
</head>
<body>
<!--form表示表单,action对应访问路径,method对应方法
    input表示输入,name是提交的name,value为提交的输入内容,submit对应的value是显示的内容
     点击提交时响应action,因为已经设置method为get,所以request自动将id=1发送过去-->
<form action="$项目名称(部署的war_exploded名称)/HelloForm" method="get">
    id:<input type="text" name="id"/>
    <input type="submit" value="提交">
</form>
</body>
</html>

使用注解@WebServlet("/XXX")与配置web.xml效果一样,但需注意访问路径

可以看到,get方法是默认的request的方法,通过get发送数据,可以直接通过url?key=value&..这样的形式,但前提是你必须知道相应的key到底是什么,也可以前端自己设置,进行表单提交,Servlet进行处理后返回对应的response。

读取表单数据

web的核心是访问资源与数据通信,访问资源包括浏览与下载,浏览html页面,下载相应资源。数据通信就是与服务器进行交互,给予服务器数据返回响应,后台如何读取数据呢,Servlet提供三个最基本方法。

在这之前,前端的表单的展现形式是标签<form>,标签包含多个字标签,<name>就是表单选项的name。

<form action="/java_servlet_jsp_war_exploded/ReadParams" method="post" target="_blank">
    <input type="checkbox" name="maths" checked="checked" /> 数学
    <input type="checkbox" name="physics"  /> 物理
    <input type="checkbox" name="chemistry" checked="checked" /> 化学
    <input type="submit" value="选择学科" />
</form>

Servlet读取表单数据有三个方法

  • getParameter():如果知道具体的name,传入即返回前端对应的value
  • getParameterNames():返回一个枚举类型的迭代器Enumeration,通过迭代获取表单的所有name。
Enumeration paraNames=request.getParameterNames();//所有表单数据参数
while(paraNames.hasMoreElements()){
    String paraName=(String)paraNames.nextElement();
}
  • getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框。
String[] paramValues=request.getParameterValues(paraName);//由name获取数据值

即前端表单与后台相互连通对应。

Http获取请求头部信息

请求request的头部包含许多重要信息

头信息描述
Accept这个头信息指定浏览器或其他客户端可以处理的 MIME 类型。值 image/png 或 image/jpeg 是最常见的两种可能值。
Accept-Charset这个头信息指定浏览器可以用来显示信息的字符集。例如 ISO-8859-1。
Accept-Encoding这个头信息指定浏览器知道如何处理的编码类型。值 gzip 或 compress 是最常见的两种可能值。
Accept-Language这个头信息指定客户端的首选语言,在这种情况下,Servlet 会产生多种语言的结果。例如,en、en-us、ru 等。
Authorization这个头信息用于客户端在访问受密码保护的网页时识别自己的身份。
Connection这个头信息指示客户端是否可以处理持久 HTTP 连接。持久连接允许客户端或其他浏览器通过单个请求来检索多个文件。值 Keep-Alive 意味着使用了持续连接。
Content-Length这个头信息只适用于 POST 请求,并给出 POST 数据的大小(以字节为单位)。
Cookie这个头信息把之前发送到浏览器的 cookies 返回到服务器。
Host这个头信息指定原始的 URL 中的主机和端口。
If-Modified-Since这个头信息表示只有当页面在指定的日期后已更改时,客户端想要的页面。如果没有新的结果可以使用,服务器会发送一个 304 代码,表示 Not Modified 头信息。
If-Unmodified-Since这个头信息是 If-Modified-Since 的对立面,它指定只有当文档早于指定日期时,操作才会成功。
Referer这个头信息指示所指向的 Web 页的 URL。例如,如果您在网页 1,点击一个链接到网页 2,当浏览器请求网页 2 时,网页 1 的 URL 就会包含在 Referer 头信息中。
User-Agent这个头信息识别发出请求的浏览器或其他客户端,并可以向不同类型的浏览器返回不同的内容。

对此,Servlet提供许多方法以访问头部信息

下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用。

序号方法 & 描述
1Cookie[] getCookies()
返回一个数组,包含客户端发送该请求的所有的 Cookie 对象。
2Enumeration getAttributeNames()
返回一个枚举,包含提供给该请求可用的属性名称。
3Enumeration getHeaderNames()
返回一个枚举,包含在该请求中包含的所有的头名。
4Enumeration getParameterNames()
返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
5HttpSession getSession()
返回与该请求关联的当前 session 会话,或者如果请求没有 session 会话,则创建一个。
6HttpSession getSession(boolean create)
返回与该请求关联的当前 HttpSession,或者如果没有当前会话,且创建是真的,则返回一个新的 session 会话。
7Locale getLocale()
基于 Accept-Language 头,返回客户端接受内容的首选的区域设置。
8Object getAttribute(String name)
以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null。
9ServletInputStream getInputStream()
使用 ServletInputStream,以二进制数据形式检索请求的主体。
10String getAuthType()
返回用于保护 Servlet 的身份验证方案的名称,例如,"BASIC" 或 "SSL",如果JSP没有受到保护则返回 null。
11String getCharacterEncoding()
返回请求主体中使用的字符编码的名称。
12String getContentType()
返回请求主体的 MIME 类型,如果不知道类型则返回 null。
13String getContextPath()
返回指示请求上下文的请求 URI 部分。
14String getHeader(String name)
以字符串形式返回指定的请求头的值。
15String getMethod()
返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
16String getParameter(String name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。
17String getPathInfo()
当请求发出时,返回与客户端发送的 URL 相关的任何额外的路径信息。
18String getProtocol()
返回请求协议的名称和版本。
19String getQueryString()
返回包含在路径后的请求 URL 中的查询字符串。
20String getRemoteAddr()
返回发送请求的客户端的互联网协议(IP)地址。
21String getRemoteHost()
返回发送请求的客户端的完全限定名称。
22String getRemoteUser()
如果用户已通过身份验证,则返回发出请求的登录用户,或者如果用户未通过身份验证,则返回 null。
23String getRequestURI()
从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
24String getRequestedSessionId()
返回由客户端指定的 session 会话 ID。
25String getServletPath()
返回调用 JSP 的请求的 URL 的一部分。
26String[] getParameterValues(String name)
返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。
27boolean isSecure()
返回一个布尔值,指示请求是否使用安全通道,如 HTTPS。
28int getContentLength()
以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。
29int getIntHeader(String name)
返回指定的请求头的值为一个 int 值。
30int getServerPort()
返回接收到这个请求的端口号。
31int getParameterMap()
将参数封装成 Map 类型。
Enumeration headerNames = request.getHeaderNames();//获取http请求头部信息name,返回一个枚举
while(headerNames.hasMoreElements()) {
    String paramName = (String)headerNames.nextElement();//http头部所定义的参数name
    String paramValue = request.getHeader(paramName);//由name获取头部信息value,即请求的当前状态
}

Http设置响应头部信息

Servlet也可以对返回的响应也可以进行设置

响应通常包括一个状态行、一些响应报头、一个空行和文档。

头信息描述
Allow这个头信息指定服务器支持的请求方法(GET、POST 等)。
Cache-Control这个头信息指定响应文档在何种情况下可以安全地缓存。可能的值有:public、private 或 no-cache 等。Public 意味着文档是可缓存,Private 意味着文档是单个用户私用文档,且只能存储在私有(非共享)缓存中,no-cache 意味着文档不应被缓存。
Connection这个头信息指示浏览器是否使用持久 HTTP 连接。值 close 指示浏览器不使用持久 HTTP 连接,值 keep-alive 意味着使用持久连接。
Content-Disposition这个头信息可以让您请求浏览器要求用户以给定名称的文件把响应保存到磁盘。
Content-Encoding在传输过程中,这个头信息指定页面的编码方式。
Content-Language这个头信息表示文档编写所使用的语言。例如,en、en-us、ru 等。
Content-Length这个头信息指示响应中的字节数。只有当浏览器使用持久(keep-alive)HTTP 连接时才需要这些信息。
Content-Type这个头信息提供了响应文档的 MIME(Multipurpose Internet Mail Extension)类型。
Expires这个头信息指定内容过期的时间,在这之后内容不再被缓存。
Last-Modified这个头信息指示文档的最后修改时间。然后,客户端可以缓存文件,并在以后的请求中通过 If-Modified-Since 请求头信息提供一个日期。
Location这个头信息应被包含在所有的带有状态码的响应中。在 300s 内,这会通知浏览器文档的地址。浏览器会自动重新连接到这个位置,并获取新的文档。
Refresh这个头信息指定浏览器应该如何尽快请求更新的页面。您可以指定页面刷新的秒数。
Retry-After这个头信息可以与 503(Service Unavailable 服务不可用)响应配合使用,这会告诉客户端多久就可以重复它的请求。
Set-Cookie这个头信息指定一个与页面关联的 cookie。

Servlet提供一系列setter()方法对其响应进行相应的设置。

序号方法 & 描述
1String encodeRedirectURL(String url)
为 sendRedirect 方法中使用的指定的 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
2String encodeURL(String url)
对包含 session 会话 ID 的指定 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
3boolean containsHeader(String name)
返回一个布尔值,指示是否已经设置已命名的响应报头。
4boolean isCommitted()
返回一个布尔值,指示响应是否已经提交。
5void addCookie(Cookie cookie)
把指定的 cookie 添加到响应。
6void addDateHeader(String name, long date)
添加一个带有给定的名称和日期值的响应报头。
7void addHeader(String name, String value)
添加一个带有给定的名称和值的响应报头。
8void addIntHeader(String name, int value)
添加一个带有给定的名称和整数值的响应报头。
9void flushBuffer()
强制任何在缓冲区中的内容被写入到客户端。
10void reset()
清除缓冲区中存在的任何数据,包括状态码和头。
11void resetBuffer()
清除响应中基础缓冲区的内容,不清除状态码和头。
12void sendError(int sc)
使用指定的状态码发送错误响应到客户端,并清除缓冲区。
13void sendError(int sc, String msg)
使用指定的状态发送错误响应到客户端。
14void sendRedirect(String location)
使用指定的重定向位置 URL 发送临时重定向响应到客户端。
15void setBufferSize(int size)
为响应主体设置首选的缓冲区大小。
16void setCharacterEncoding(String charset)
设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
17void setContentLength(int len)
设置在 HTTP Servlet 响应中的内容主体的长度,该方法设置 HTTP Content-Length 头。
18void setContentType(String type)
如果响应还未被提交,设置被发送到客户端的响应的内容类型。
19void setDateHeader(String name, long date)
设置一个带有给定的名称和日期值的响应报头。
20void setHeader(String name, String value)
设置一个带有给定的名称和值的响应报头。
21void setIntHeader(String name, int value)
设置一个带有给定的名称和整数值的响应报头。
22void setLocale(Locale loc)
如果响应还未被提交,设置响应的区域。
23void setStatus(int sc)
为该响应设置状态码。
response.setIntHeader("Refresh",1);//设置响应头部信息,5秒自动刷新
response.setContentType("text/html;charset=UTF-8");//设置响应头部

Http设置头部状态码

状态码就是http报文头部表示当前报文状态的信息

以下是可能从 Web 服务器返回的 HTTP 状态码和相关的信息列表:

代码消息描述
100Continue只有请求的一部分已经被服务器接收,但只要它没有被拒绝,客户端应继续该请求。
101Switching Protocols服务器切换协议。
200OK请求成功。
201Created该请求是完整的,并创建一个新的资源。
202Accepted该请求被接受处理,但是该处理是不完整的。
203Non-authoritative Information 
204No Content 
205Reset Content 
206Partial Content 
300Multiple Choices链接列表。用户可以选择一个链接,进入到该位置。最多五个地址。
301Moved Permanently所请求的页面已经转移到一个新的 URL。
302Found所请求的页面已经临时转移到一个新的 URL。
303See Other所请求的页面可以在另一个不同的 URL 下被找到。
304Not Modified 
305Use Proxy 
306Unused在以前的版本中使用该代码。现在已不再使用它,但代码仍被保留。
307Temporary Redirect所请求的页面已经临时转移到一个新的 URL。
400Bad Request服务器不理解请求。
401Unauthorized所请求的页面需要用户名和密码。
402Payment Required您还不能使用该代码。
403Forbidden禁止访问所请求的页面。
404Not Found服务器无法找到所请求的页面。.
405Method Not Allowed在请求中指定的方法是不允许的。
406Not Acceptable服务器只生成一个不被客户端接受的响应。
407Proxy Authentication Required在请求送达之前,您必须使用代理服务器的验证。
408Request Timeout请求需要的时间比服务器能够等待的时间长,超时。
409Conflict请求因为冲突无法完成。
410Gone所请求的页面不再可用。
411Length Required"Content-Length" 未定义。服务器无法处理客户端发送的不带 Content-Length 的请求信息。
412Precondition Failed请求中给出的先决条件被服务器评估为 false。
413Request Entity Too Large服务器不接受该请求,因为请求实体过大。
414Request-url Too Long服务器不接受该请求,因为 URL 太长。当您转换一个 "post" 请求为一个带有长的查询信息的 "get" 请求时发生。
415Unsupported Media Type服务器不接受该请求,因为媒体类型不被支持。
417Expectation Failed 
500Internal Server Error未完成的请求。服务器遇到了一个意外的情况。
501Not Implemented未完成的请求。服务器不支持所需的功能。
502Bad Gateway未完成的请求。服务器从上游服务器收到无效响应。
503Service Unavailable未完成的请求。服务器暂时超载或死机。
504Gateway Timeout网关超时。
505HTTP Version Not Supported服务器不支持"HTTP协议"版本。

一般只需要响应头部设置状态码,返回信息即可 

这些方法通过 HttpServletResponse 对象可用。

序号方法 & 描述
1public void setStatus ( int statusCode )
该方法设置一个任意的状态码。setStatus 方法接受一个 int(状态码)作为参数。如果您的响应包含了一个特殊的状态码和文档,请确保在使用 PrintWriter 实际返回任何内容之前调用 setStatus。
2public void sendRedirect(String url)
该方法生成一个 302 响应,连同一个带有新文档 URL 的 Location 头。
3public void sendError(int code, String message)
该方法发送一个状态码(通常为 404),连同一个在 HTML 文档内部自动格式化并发送到客户端的短消息。
response.sendError(777, "响应状态码,可自行设置");

过滤器Filter

过滤器用于在请求与响应之前进行拦截并处理,类似于面向切面的概念,请求不能一味的直接交给Servlet,先要进行拦截,拦截时对一系列信息进行检查或者包装等等操作,最终再返回,通过继承Filter接口实现。过滤器当然可以有多个,因此就形成了过滤链,用类 FilterChain表示,其只有一个doFilter()方法,表示将当前请求或响应交给下一个过滤器。

过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:

序号方法 & 描述
1public void doFilter (ServletRequest, ServletResponse, FilterChain)
该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。
2public void init(FilterConfig filterConfig)
web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
3public void destroy()
Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。

Filter的生命周期存在于整个服务器的运行周期,当服务器启动时,创建Filter对象并调用init(),filter对象只会创建一次,init方法也只会执行一次,之后会根据web.xml或注解配置的url启动对应的过滤器,每有一次访问即调用一次doFilter()方法,最后服务器关闭时调用destory()。

package study;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//Filter接口实现过滤,用于在请求与响应之前进行拦截并处理然后再交给Servlet
//Filter接口主要要实现三个方法

/**
 *       public void init(FilterConfig filterConfig)
 * web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
 *       public void doFilter (ServletRequest, ServletResponse, FilterChain)
 * 该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。
 *       public void destroy()
 * Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。
 */
//使用web.xml与注解类似,<filter>标签初始化一个FilterConfig对象,传给init
@WebFilter("/*")
public class LogFilter implements Filter {
    @Override
    public void init(FilterConfig config){
        System.out.println("过滤初始化-LogFilter-init");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws ServletException,IOException{
        System.out.println("开始过滤-LogFilter-doFilter");
        chain.doFilter(request,response);//将请求与响应传入过滤链
    }

    @Override
    public void destroy() {
        System.out.println("过滤销毁-LogFilter-destroy");
    }
}

同Servlet一样,Filter也要在web.xml下进行相应配置或使用注解。

<filter>
  <filter-name>LogFilter</filter-name>
  <filter-class>com.runoob.test.LogFilter</filter-class>
  <init-param>
    <param-name>filterName</param-name>
    <param-value>filterValue</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>LogFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

/*代表所有url都过滤

其中<init-param>标签在init()中有用,init()传入的FilterConfig即代表过滤器初始实例,可以调用

getInitParameter("filterName");

方法获取配置的对应的filterValue

通过使用注解@WebFilter("/XXX")效果相同

当然可以使用多个过滤器,调用过滤链方法即可

异常处理

如果请求抛出异常或包含错误状态码(404等),想要返回对应的错误页面,也应该对应一个Servlet,即发生错误时跳转到对应的Servlet。同时在web.xml中设置标签<error-page>

<error-page>包含子标签<error-code>对应的错误状态码,<exception-type>抛出异常类型,<location>跳转到对应的Servlet

<error-page>
    <error-code>404</error-code>
    <location>/ErrorHandler</location>
</error-page>
<error-page>
    <exception-type>java.io.IOException</exception-type >
    <location>/ErrorHandler</location>
</error-page>

如果只有<location>则默认所有错误都进行跳转

package study;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ErrorHandler")
public class ErrorHandler extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        Throwable throwable=(Throwable)request.getAttribute("javax.servlet.error.exception");//获取异常属性
        Integer statusCode=(Integer)request.getAttribute("javax.servlet.error.status_code");//获取状态码
        String servletName=(String)request.getAttribute("javax.servlet.error.servlet_name");//获取servlet
        servletName=servletName==null?"未知Servlet":servletName;

        String requestUri=(String)request.getAttribute("javax.servlet.error.request_uri");//获取请求uri
        requestUri=requestUri==null?"未知URI":requestUri;

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String title = " Error/Exception 信息处理";

        String docType = "<!DOCTYPE html>\n";
        out.println(docType +
                "<html>\n" +
                "<head><title>" + title + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n");
        out.println("<h1>抛出错误时的显示页面</h1>");
        if (throwable == null && statusCode == null){
            out.println("<h2>错误信息丢失</h2>");
            out.println("请返回 <a href=\"" +
                    response.encodeURL("http://localhost:8080/") +
                    "\">主页</a>。");
        }else if (statusCode != null) {
            out.println("错误代码 : " + statusCode);//如果错误状态码则显示状态码
        }else{//如果抛出异常则显示异常信息
            out.println("<h2>错误信息</h2>");
            out.println("Servlet Name : " + servletName +
                    "</br></br>");
            out.println("异常类型 : " +
                    throwable.getClass( ).getName( ) +
                    "</br></br>");
            out.println("请求 URI: " + requestUri +
                    "<br><br>");
            out.println("异常信息: " +
                    throwable.getMessage( ));
        }
        out.println("</body></html>");
    }
    // 处理 POST 方法请求的方法
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

其中通过getAttribute()获取request的相关属性信息,返回一个Object,,需要向下转型,如

Throwable throwable=(Throwable)request.getAttribute("javax.servlet.error.exception");//获取异常属性

Integer statusCode=(Integer)request.getAttribute("javax.servlet.error.status_code");//获取状态码

String servletName=(String)request.getAttribute("javax.servlet.error.servlet_name");//获取servlet

Cookie处理

如果第一次访问服务器,服务器读取表单数据,然后返回的响应中设置相应cookie,下一次发送服务器的cookie中就有相应的信息,主要目的就是方便用户。

第一次读取:Browser--->Server(读取Cookie,没有信息,response设置Cookie)--->response返回给Browse,Browse设置Cookie

已经有Cookie:Browser---->Server(读取Cookie获取信息)<->DataBase                                                                                                             

Servlet中的Cookie处理主要使用类Cookie,代表一个Cookie信息

Servlet Cookie 处理需要对中文进行编码与解码,方法如下:

String   str   =   java.net.URLEncoder.encode("中文","UTF-8");            //编码
String   str   =   java.net.URLDecoder.decode("编码后的字符串","UTF-8");   // 解码

Cookie 通常设置在 HTTP 头信息中,,Set-Cookie 头包含了一个名称值对、一个 GMT 日期、一个路径和一个域。名称和值会被 URL 编码。Cookie以键值对的形式展现。

以下是在 Servlet 中操作 Cookie 时可使用的有用的方法列表。

序号方法 & 描述
1public void setDomain(String pattern)
该方法设置 cookie 适用的域,例如 runoob.com。
2public String getDomain()
该方法获取 cookie 适用的域,例如 runoob.com。
3public void setMaxAge(int expiry)
该方法设置 cookie 过期的时间(以秒为单位)。如果不这样设置,cookie 只会在当前 session 会话中持续有效。
4public int getMaxAge()
该方法返回 cookie 的最大生存周期(以秒为单位),默认情况下,-1 表示 cookie 将持续下去,直到浏览器关闭。
5public String getName()
该方法返回 cookie 的名称。名称在创建后不能改变。
6public void setValue(String newValue)
该方法设置与 cookie 关联的值。
7public String getValue()
该方法获取与 cookie 关联的值。
8public void setPath(String uri)
该方法设置 cookie 适用的路径。如果您不指定路径,与当前页面相同目录下的(包括子目录下的)所有 URL 都会返回 cookie。
9public String getPath()
该方法获取 cookie 适用的路径。
10public void setSecure(boolean flag)
该方法设置布尔值,表示 cookie 是否应该只在加密的(即 SSL)连接上发送。
11public void setComment(String purpose)
设置cookie的注释。该注释在浏览器向用户呈现 cookie 时非常有用。
12public String getComment()
获取 cookie 的注释,如果 cookie 没有注释则返回 null。

通过 Servlet 设置 Cookie 包括三个步骤:

(1) 创建一个 Cookie 对象:调用带有 cookie 名称和 cookie 值的 Cookie 构造函数,cookie 名称和 cookie 值都是字符串。

Cookie cookie = new Cookie("key","value");

(2) 设置最大生存周期:使用 setMaxAge 方法来指定 cookie 能够保持有效的时间(以秒为单位)。下面将设置一个最长有效期为 24 小时的 cookie。

cookie.setMaxAge(60*60*24); 

(3) 发送 Cookie 到 HTTP 响应头:使用 response.addCookie 来添加 HTTP 响应头中的 Cookie,如下所示:

response.addCookie(cookie);

读取Cookie也很简单:

Cookie[] cookies=request.getCookies();//获取cookies

删除Cookie:

调用Cookie的setMaxAge()方法将最大生存周期设置为0就相当于删除Cookie

示例:

package study;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;

@WebServlet("/SetAndReadCookie")
public class SetAndReadCookie extends HttpServlet {
    private static final long serialVersionUID=1L;

    public SetAndReadCookie(){
        super();
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException,IOException{
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");//都设置字符集

        Cookie[] cookies=request.getCookies();//获取cookies
        PrintWriter out=response.getWriter();

        out.println("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head><title>" + "读取/设置Cookie" + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" );
        //如果访问时没有cookie则设置cookie
        if(cookies.length==3){
            Cookie id=new Cookie("id",request.getParameter("id"));//由表单获取数据并设置cookie
            Cookie name=new Cookie("name", URLEncoder.encode(request.getParameter("name"),"UTF-8"));
            id.setMaxAge(24*60*60);//设置服务器的cookie的存在时间
            name.setMaxAge(24*60*60);
            response.addCookie(id);//在响应头部中增加cookie即可,服务器会保存,下一次自动发给服务器
            response.addCookie(name);

            out.print("第一次访问网站或者cookie过期,已重置cookie");
        }else{
            out.println("<h2>已获取到Cookie,Cookie 名称和值</h2>");
            for(Cookie cookie:cookies){
                out.print("名称:" + cookie.getName( ) + ",");//读取cookie
                out.print("值:" +  URLDecoder.decode(cookie.getValue(), "utf-8") +" <br/>");
            }
        }
        out.println("</body></html>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

Session会话

session会话是一个抽象概念,session存储于服务器内存中,相当于服务器存储连接用户信息的临时容器,session可以用cookie,重写url
等方式实现,每一次连接会在服务器产生一个session,使用session-id进行标识,每刷新一次或者开一个子窗口浏览器会自动偷偷发送session-id给服务器
对于Servlet来说就是cookie中的JSESSIONID,通过识别JSESSIONID服务器知道仍然是这个链接所以直接可以抽取出信息并进行处理,如果不是这样,因为http是无状态
连接,所以不会保存访问信息,不能浏览网页的时候刷新一下就重新登录一次吧?因此就出现了session这个抽象概念,访问静态html页面没必要创建session,
访问动态页面,如用户登录时就需要,当然浏览器请求或者Servlet自动创建,用户并不知道,这还是为了提供更好的用户体验,可自行设置session的存在时间。

session的实现方式

1.cookie

一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。

2.隐藏的表单字段

一个 Web 服务器可以发送一个隐藏的 HTML 表单字段,以及一个唯一的 session 会话 ID,如下所示:

<input type="hidden" name="sessionid" value="12345">

该条目意味着,当表单被提交时,指定的名称和值会被自动包含在 GET 或 POST 数据中。每次当 Web 浏览器发送回请求时,session_id 值可以用于保持不同的 Web 浏览器的跟踪。

这可能是一种保持 session 会话跟踪的有效方式,但是点击常规的超文本链接(<A HREF...>)不会导致表单提交,因此隐藏的表单字段也不支持常规的 session 会话跟踪。

3.URL 重写

您可以在每个 URL 末尾追加一些额外的数据来标识 session 会话,服务器会把该 session 会话标识符与已存储的有关 session 会话的数据相关联。

例如,http://w3cschool.cc/file.htm;sessionid=12345,session 会话标识符被附加为 sessionid=12345,标识符可被 Web 服务器访问以识别客户端。

Servlet中的session

Servlet 提供 HttpSession 接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式。

Servlet 容器使用这个接口来创建一个 HTTP 客户端和 HTTP 服务器之间的 session 会话。会话持续一个指定的时间段,跨多个连接或页面请求。

通过调用 HttpServletRequest 的公共方法 getSession() 来获取 HttpSession 对象,如下所示:

HttpSession session = request.getSession();

你需要在向客户端发送任何文档内容之前调用 request.getSession()。下面总结了 HttpSession 对象中可用的几个重要的方法:

序号方法 & 描述
1public Object getAttribute(String name)
该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。
2public Enumeration getAttributeNames()
该方法返回 String 对象的枚举,String 对象包含所有绑定到该 session 会话的对象的名称。
3public long getCreationTime()
该方法返回该 session 会话被创建的时间,自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
4public String getId()
该方法返回一个包含分配给该 session 会话的唯一标识符的字符串。
5public long getLastAccessedTime()
该方法返回客户端最后一次发送与该 session 会话相关的请求的时间自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。
6public int getMaxInactiveInterval()
该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。
7public void invalidate()
该方法指示该 session 会话无效,并解除绑定到它上面的任何对象。
8public boolean isNew()
如果客户端还不知道该 session 会话,或者如果客户选择不参入该 session 会话,则该方法返回 true。
9public void removeAttribute(String name)
该方法将从该 session 会话移除指定名称的对象。
10public void setAttribute(String name, Object value) 
该方法使用指定的名称绑定一个对象到该 session 会话。
11public void setMaxInactiveInterval(int interval)
该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。
package study;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

@WebServlet("/SessionTrack")
public class SessionTrack extends HttpServlet {
    private static final long serialVersionUID=1L;
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
        HttpSession session=request.getSession(true);//如果不存在session对象则创建

        Date createTime=new Date(session.getCreationTime());//获取session的创建时间
        Date lastAccessTime=new Date(session.getLastAccessedTime());//获取最后一次传递session的时间
        SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置简单日期格式

        /*
        session会话是一个抽象概念,session存储于服务器内存中,相当于服务器存储连接用户信息的临时容器,session可以用cookie,重写url
        等方式实现,每一次连接会在服务器产生一个session,使用session-id进行标识,每刷新一次或者开一个子窗口浏览器会自动偷偷发送session-id给服务器
        对于Servlet来说就是cookie中的JSESSIONID,通过识别JSESSIONID服务器知道仍然是这个链接所以直接可以抽取出信息并进行处理,如果不是这样,因为http是无状态
        连接,所以不会保存访问信息,不能浏览网页的时候刷新一下就重新登录一次吧?因此就出现了session这个抽象概念,访问静态html页面没必要创建session,
        访问动态页面,如用户登录时就需要,当然浏览器请求或者Servlet自动创建,用户并不知道,这还是为了提供更好的用户体验
         */
        String visitCountKey ="visitCount";
        int visitCount = 0;

        String userKey ="userID";//session信息值存储于本地服务器
        String user ="LSL";
        //如果该session没有设置相应的key则直接在服务器设置需要的键值
        if(session.getAttribute(visitCountKey) == null) {
            session.setAttribute(visitCountKey, 0);
        }

        // 检查是是新的访问者(由session追踪)
        if (session.isNew()){
            session.setAttribute(userKey, user);
        } else {
            visitCount = (Integer)session.getAttribute(visitCountKey);
            visitCount++;
        }
        session.setAttribute(visitCountKey,  visitCount);//更新session

        // 设置响应内容类型
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        out.println("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head><title>" + "Servlet Session 会话实例 "+ "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + "Servlet Session 会话实例 " + "</h1>\n" +
                "<h2 align=\"center\">Session 信息</h2>\n" +
                "<table border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "  <th>Session 信息</th><th>值</th></tr>\n" +
                "<tr>\n" +
                "  <td>id</td>\n" +
                "  <td>" + session.getId() + "</td></tr>\n" +
                "<tr>\n" +
                "  <td>创建时间</td>\n" +
                "  <td>" +  df.format(createTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>最后访问时间</td>\n" +
                "  <td>" + df.format(lastAccessTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>用户 ID</td>\n" +
                "  <td>" + user +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>访问统计:</td>\n" +
                "  <td>" + visitCount + "</td></tr>\n" +
                "</table>\n" +
                "</body></html>");
    }
}

这样服务器自动创建session实例并保存session信息,在规定时间内由session-id标识每一个session,如果是处于同一个session则通过getAttribute()等方法获取原来的信息,如果是第一次连接则创建session并通过setAttribute()等方法设置信息。

访问数据库

最原始的方式即通过JDBC访问数据库。

以mysql8.0.15为例

1.导入JDBC驱动

Class.forName(JDBC_DRIVER);//8.0.15中,JDBC_DRIVER="com.mysql.cj.jdbc.Driver";

2.连接数据库,返回连接对象

Connection connection= DriverManager.getConnection(DB_URL,USER,PASSWORD);

8.0.15中,DB_URL后要加上时区,否则抛出异常

DB_URL="jdbc:mysql://localhost:3306/lsl?serverTimezone=UTC";

3.进行实际连接,返回操作对象

Statement statement=connection.createStatement();

4.执行sql,返回结果集或者boolean值

ResultSet resultSet=statement.executeQuery(sql);
package study;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;

@WebServlet("/DatabaseAccess")
public class DatabaseAccess extends HttpServlet {
    private static final long serialVersionUID=1L;

    static final String JDBC_DRIVER="com.mysql.cj.jdbc.Driver";
    static final String DB_URL="jdbc:mysql://localhost:3306/lsl?serverTimezone=UTC";
    static final String USER="root";
    static final String PASSWORD="123456";

    public DatabaseAccess(){
        super();
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
        Connection connection=null;
        Statement statement=null;
        String sql="select * from test";

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>\n"+
                "<html>\n" +
                "<head><title>" +"Servlet数据库访问" + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + "Servlet数据库访问" + "</h1>\n");

        try {
            Class.forName(JDBC_DRIVER);
            connection= DriverManager.getConnection(DB_URL,USER,PASSWORD);
            statement=connection.createStatement();
            ResultSet resultSet=statement.executeQuery(sql);
            //迭代结果集
            while (resultSet.next()){
                out.println("ID: " + resultSet.getString("id"));
                out.println(",姓名:" + resultSet.getString("name"));
                out.println(", 性别: " + resultSet.getString("sex"));
                out.println(", 年龄: " + resultSet.getString("age"));
                out.println("<br />");
            }
            resultSet.close();//关闭
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                //迭代完之后记得关闭资源
                statement.close();
                connection.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException{
        doGet(request,response);
    }
}

前端与数据库通过中间servlet交互,如果想要提取表单值并插入数据库中,可以这样操作:

/编写预处理 SQL 语句
String sql= "INSERT INTO websites1 VALUES(?,?,?,?,?)";

//实例化 PreparedStatement
ps = conn.prepareStatement(sql);
//传入参数,这里的参数来自于一个带有表单的jsp文件,很容易实现
ps.setString(1, request.getParameter("id"));
ps.setString(2, request.getParameter("name"));
ps.setString(3, request.getParameter("url"));
ps.setString(4, request.getParameter("alexa"));
ps.setString(5, request.getParameter("country"));

//执行数据库更新操作,不需要SQL语句
ps.executeUpdate();
sql = "SELECT id, name, url FROM websites1";
ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();//获取查询结果

网页重定向

当因为某种原因需要进行页面的自动跳转时,即页面重定向

servlet中页面重定向有两种方法

1.response调用sendRedirect()方法

2.设置头部状态码及指定跳转页面

String site = "http://www.baidu.com" ;
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site); 
package study;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/PageRedirect")
public class PageRedirect extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
        response.setContentType("text/html;charset=UTF-8");
        response.sendRedirect("http://www.baidu.com");//调用sendRedirect()重定向
    }
    public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException{
        doGet(request,response);
    }
}

网页访问量计数器

单个网页只需要在初始化servlet的init()方法中初始化计数器为0即可(或者如果服务器重启则从数据库中读取数据),由servlet的生命周期可知,每次访问都会调用doGet()等方法,对应计数器加1即可。或者使用过滤器Filter即可。

总点击量可通过设置过滤器filter完成。

Servlet 自动刷新页面

调用方法设置头部自动刷新即可

public void setIntHeader(String header, int headerValue)

如:setIntHeader("Refresh",1)即设置页面每隔一秒自动刷新一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值