Servlet相关知识点
一、引言
1.1C/S架构和B/S架构
C/S和B/S是软件发展过程中出现的两种软件架构方式。
1.2C/S架构(Client/Server客户端/服务器)
- 特点:必须在客户端安装特定软件
- 优点:图形效果显示较好(如:3D游戏)
- 缺点:服务器软件和功能进行升级,客户端也必须升级、不利于维护
- 常见的C/S程序:QQ、微信等
1.3B/S架构(Browser/Server浏览器/服务器)
- 特点:无需安装客户端,任何浏览器都可直接访问
- 优点:涉及到功能的升级,只需要升级服务器端
- 缺点:图形显示效果不如C/S架构
- 需要通过HTTP协议访问
二、服务器
2.1概念
2.1.1什么是Web
Web(World Wide Web)称为万维网,简单理解就是网站,它用来表示Internet主机上供外界访问的资源。
Internet上供外界访问的额资源分为两大类
- 静态资源:指Web页面中供人们浏览的数据始终是不变的。(HTML、CSS)
- 动态资源:指Web页面中供人们浏览的数据是由程序产生的,不同时间点,甚至不同设备访问Web页面看到的内容各不相同。(JSP/Servlet)
- 在Java中,动态Web资源开发技术我们统称为Java Web。
2.1.2什么是Web服务器
Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问。
2.2常见服务器
- 开源:OpenSource(1、开放源代码 2、免费)
- Tomcat(主流Web服务器之一,适合初学者 )
- jetty(淘宝,运行效率比Tomcat高)
- resin(新浪,所有开源服务器软件中,运行效率最高的)
- 三者的用法从代码角度完全相同,只有在开启、关闭服务器软件时对应的命令稍有区别。掌握一个即掌握所有
- 收费
- WebLogic(Oracle)
- WebSphere(IBM)
- 提供相应的服务与支持,软件大,耗资源
2.3Tomcat服务器
Tomcat时Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,免费开源、并支持Servlet和JSP规范。目前Tomcat最新版本为9.0。
Tomcat技术先进、性能稳定,深受Java爱好者喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
2.4Tomcat安装
2.4.1下载
官网下载(http://tomcat.apache.org)Tomcat8.5解压缩版本
2.4.2解压安装
将Tomcat解压到一个没有特殊符号的目录中(一般纯英文即可)
注意
- 不建议将服务器软件放在磁盘层次很多的文件夹
- 不建议放在中文路径下
2.4.3Tomcat目录结构
文件夹 | 说明 | 备注 |
---|---|---|
bin | 该目录下存放的是二进制可执行文件 | startup.bat启动Tomcat、shutdown.bat停止Tomcat |
conf | 这是一个非常重要的目录,这个目录下有两个最为重要的文件server.xml和web.xml | server.xml:配置整个服务器信息。例如修改端口号,编码格式等。 web.xml:项目部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。 |
lib | Tomcat的类库,里面存放Tomcat运行所需要的jar文件。 | |
logs | 存放日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,异常也会记录在日志文件中。 | |
temp | Tomcat的临时文件,这个目录下的东西在停止Tomcat后删除。 | |
webapps | 存放web项目的目录,其中每个文件夹都是一个项目;其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。 | |
work | 运行时生成的文件,最终运行的文件都在这里。 | 当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。 |
2.5Tomcat启动和停止
2.5.1启动
进入tomcat安装目录bin下,双击startup.bat启动程序,出现如下界面
2.5.2验证
打开浏览器,输入http://localhost:8080
如果出现以下界面证明Tomcat启动成功。
2.5.3停止
Tomcat默认端口号为8080,可以通过conf/server.xml文件修改
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
- 注意:修改端口号需要重新启动Tomcat才能生效
2.6项目部署及访问静态资源
Tomcat是Web服务器,我们的项目应用是部署在webapps下,然后通过特定的URL访问。
2.6.1创建项目
- 在webapps中建立文件夹(项目应用),比如:myweb
- 创建WEB-INF文件夹,用于存放项目的核心内容
- 创建classes,用于存放.class文件
- 创建lib,用于存放jar文件
- 创建web.xml,项目配置文件(到ROOT项目下的WEB-INF复制即可)
- 把网页hello.html复制到myweb文件夹中,与WEB-INF在同级目录
2.6.2URL访问资源
浏览器地址中输入URL:http://localhost:8080/myweb/hello.html
- 经验:URL主要有4部分组成:协议、主机、端口、资源路径
2.6.3Tomcat响应流程图
2.7常见错误
2.7.1Tomcat控制台闪退
闪退问题是由于JAVA_HOME配置导致的,检查JAVA_HOME配置是否正确
2.7.2 404
访问资源不存在,出现404错误
三、Servlet
3.1概念
- Servlet:Server Applet的简称,是服务器端的程序(代码、功能实现),可交互式的处理客户端发送到服务端的请求,并完成操作响应。
- 动态网页技术
- JavaWeb程序开发的基础,JavaEE规范(一套接口)的一个组成部分。
3.1.1Servlet作用
- 接收客户端请求,完成操作。
- 动态生成网页(页面数据可变)。
- 将包含操作结果的动态网页响应给客户端。
3.2Servlet开发步骤
3.2.1搭建开发环境
将Servlet相关jar包(lib\servlet-api.jar)配置到classpath中
3.2.2编写Servlet
- 实现javax.servlet.Servlet
- 重写5个主要方法
- 在核心的servlet()方法中编写输出语句,打印访问结果
package com.zjl.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("My First Servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
3.2.3部署Servlet
编译MyServlet后,将生成的.class文件放在WEB-INF/classes文件夹中。
3.2.4配置Servlet
编写WEB-INF下项目配置文件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_4_0.xsd"
version="4.0">
<!--1、添加servlet节点-->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.zjl.servlet.MyServlet</servlet-class>
</servlet>
<!--2、添加servlet-mapping节点-->
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
</web-app>
- 注意:url-pattern配置的内容就是浏览器地址栏输入的URL中项目名称后的资源的内容
3.3运行测试
启动Tomcat,在浏览器地址栏中输入http://localhost:8080/myweb/myservlet访问,在Tomcat中打印时间表示成功。
3.4创建错误
3.4.1 500错误
服务端出现异常
四、IDEA创建Web项目
4.1IDEA创建Web项目
创建项目窗口,选择JavaEE7,并勾选Web Application
输入项目名称和项目保存位置,点击Finish,完成项目创建
Web项目目录介绍
4.2IDEA开发Servlet
使用开发工具编写Servlet,仍要手工导入servlet-api.jar文件,并与项目关联
4.2.1编写Servlet
创建MyServlet,实现Servlet接口,覆盖5个方法
4.2.2配置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_4_0.xsd"
version="4.0">
<!--1、添加servlet节点-->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.zjl.servlet.MyServlet</servlet-class>
</servlet>
<!--2、添加servlet-mapping节点-->
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
</web-app>
4.2.3部署Web项目
- 在Tomcat的webapps目录下,新建WebProject项目文件夹
- 创建WEB-INF,存放核心文件
- 在WEB-INF下,创建classes文件夹,将编译后的MyServlet.class文件复制至此。
- 问题:每当我们编写了新的Servlet或者重新编译,都需要手工将新的.class部署到Tomcat中,较为麻烦。如何实现自动部署?
4.3IDEA部署Web项目
前面我们是在Tomcat的webapps目录新建应用程序目录myweb,然后把静态资源和Servlet复制到相关目录下。使用IDEA不需要我们复制了。可以通过IDEA集成Tomcat服务器,实现自动部署。
4.3.1 IDEA集成Tomcat
点击File选项,选择Settings
选择Build,Execution,Deployment下的Application Servers。
点击+号,选择Tomcat Server
选择Tomcat安装目录,点击OK即可
最后,点击OK
4.3.2项目部署Tomcat
点击Add Configuration
点击+号,选择Tomcat Server,选择Local
点击+号,选择Artifact,添加当前项目
点击运行按钮,即可运行项目
4.4其他操作
4.4.1关联第三方jar包
在WEB-INF目录下新建lib目录
输入lib目录
复制jar包到lib目录中
右击lib目录,选择Add as Library…
选择Project Library完成。
- Global Library表示所有工程都可以使用
- Project Library表示当前工程中所有模块都可以使用。
- Module Library表示当前模块可以使用
4.4.2如何导出war包
项目完成后,有时候需要打成war方便部署。war包可以直接放入Tomcat的webapps目录中,启动Tomcat后自动解压,即可访问。
点击项目结构
选择Artifacts,点击+号
选择Archive---->For…
构建项目
在out\artifacts\目录中,查看生产的war包,把war放入Tomcat的webapps目录,启动Tomcat自动解压即可访问。
五、HTTP协议
5.1什么是HTTP
超文本传输协议(HTP,HyperText Transfer Protocol)式互联网上应用最为广泛的一种网络协议,是一个基于请求与响应模式的、无状态的、运行于TCP协议基础之上。
5.2HTTP协议特点
- 支持客户端(浏览器)/服务器模式。
- 简单快速:客户端只向服务器发送请求方法和路径,服务器即可响应数据,因而通信速度很快。请求方法常用的有GET、POST等。
- 灵活:HTTP允许传输任意类型的数据,传输的数据类型由Content-Type标识。
- 无连接:无连接指的是每次TCP连接只处理一个或多个请求,服务器处理完客户的请求后,即断开连接。采用之中方式可以节省传输时间。
- HTTP1.0版本是一个请求响应之后,直接就断开了。称为短连接。
- HTTP1.1版本不是响应之后直接就断开了,而是等几秒钟,这几秒钟之内有新的请求,那么还是通过之前的连接通道来收发消息,如果过了几秒钟用户没有发送新的请求,就会断开连接。称为长连接。
- 无状态:HTTP协议是无状态协议。
- 无状态是指协议对于事务处理没有记忆能力。
5.3HTTP协议通信流程
- 客户与服务器建立连接(三次握手)。
- 客户向服务器发送请求。
- 服务器接受请求,并根据请求返回相应的文件作为应答。
- 客户与服务器关闭连接(四次挥手)。
5.4请求报文和响应报文
5.4.1HTTP请求报文
当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息(请求报文),HTTP请求信息由4部分组成:1、请求行 请求方法/地址 URL协议/版本 2、请求头(Request Header) 3、空行 4、请求正文
5.4.2HTTP响应报文
HTTP响应报文与HTTP请求报文相似,HTTP响应也由4个部分组成:1、状态行 2、响应头(Response Header) 3、空行 4、响应正文
5.4.3常见状态码
状态代码 | 状态描述 | 说明 |
---|---|---|
200 | OK | 客户端请求成功 |
302 | Found | 临时重定向 |
403 | Forbidden | 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因 |
404 | Not Found | 请求的资源不存在,例如,输入了错误的URL。 |
500 | Internal Server Error | 服务器发生不可预期的错误,导致无法完成客户端的请求。 |
六、Servlet详解
6.1Servlet核心接口和类
在Servlet体系结构中,除了实现Servlet接口,还可以通过集成GenericServlet或HttpServlet类,完成编写。
6.1.1Servlet接口
在Servlet API中最重要的是Servlet接口,所有Servlet都会直接或间接的与该接口发生联系,或是直接实现该接口,或间接继承自实现了该接口的类。该接口包括以下五个方法:
- init(ServletConfig config)
- ServletConfig getServletConfig()
- service(ServletRequest req,ServletResponse resp)
- String getServletInfo()
- destroy()
6.1.3HttpServlet类
HttpServlet是继承GenericServlet的基础上进一步的扩展。提供将要被子类化以创建适用于Web站点的HTTP Servlet的抽象类。
HttpServlet的子类至少必须重写一个方法,该方法通常是以下这些方法之一:doGet,如果servlet支持HTTP GET请求 doPost,用于HTTP POST请求 doPut,用于HTTP PUT请求 doDelete,用于HTTP DELETE请求
6.2Servlet两种创建方式
6.2.1实现接口Servlet
package com.zjl.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* Servlet创建的第一种方式:实现接口Servlet
*/
public class HelloServlet2 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("OK");
servletResponse.getWriter().println("welcome use servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
- 该方式比较麻烦,需要实现几口中所有方法
6.2.2继承HttpServlet(推荐)
package com.zjl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Servlet implementation class HelloServlet
* Servlet的第二种创建方式,继承HttpServlet,也是开发中推荐的
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("welcome use servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.2.3常见错误
- HTTP Status 404资源找不到
- 第一种情况:地址书写错误。
- 第二种情况:地址没有问题,把IDEA项目中out目录删除,然后重新运行。
- Servlet地址配置重复。both mapped to the url-pattern [/helloservlet] which is not permitted。
- Servlet地址配置错误。比如没有写/Invalid [helloservlet2] in servlet mapping。
6.3Servlet两种配置方式
6.3.1使用web.xml(Servlet2.5之前使用)
<?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_4_0.xsd"
version="4.0">
<display-name>Web_Test01</display-name>
<!--Servlet的第二种配置-->
<!--Servlet配置-->
<servlet>
<!--名称-->
<servlet-name>hello2</servlet-name>
<!--Servlet的全称类名-->
<servlet-class>com.zjl.servlet.HelloServlet</servlet-class>
<!--启动的优先级,数字越小越先起作用-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--映射配置-->
<servlet-mapping>
<!--名称-->
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
6.3.2配置属性
url-pattern定义匹配规则,取值说明:
精确匹配 /具体的名称 只有url路径是具体的名称的时候才会触发Servlet
后缀匹配 `*`.xxx 只要是以xxx结尾的就匹配触发Servlet
通配符匹配 /`*` 匹配所有请求,包含服务器的所有资源
通配符匹配 / 匹配所有请求,包含服务器的所有资源,不包括.jsp
load-on-startup
1.元素标记容器是否应该在web应用程序启动的时候就加载这个servlet。
2.它的值必须是一个整数,表示servlet被加载的先后顺序。
3.如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
4.如果值为正整数或者0时,表示容器在应用启动时就夹在并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
6.3.3使用注解(Servlet3.0后支持,推荐)
package com.zjl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Servlet implementation class HelloServlet
* 演示Servlet注解式配置
*/
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("welcome use servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.3.4@WebServlet注解常用属性
- name:Servlet名字(可选)
- value:配置url路径,可以配置多个
- urlPatterns:配置url路径,和value作用一样,不能同时使用
- loadOnStartup:配置Servlet的创建的时机,如果是0或者正数,启动程序时创建,如果是负数,则访问时创建。数字越小优先级越高。
七、Servlet应用
7.1request对象
在Servlet中用来处理客户端请求需要使用doGet或doPost方法的request对象
7.1.1get和post区别
get请求
- get提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连
- get方式明文传递,数据量小,不安全
- 效率高,浏览器默认请求方式为GET请求
- 对应的Servlet的方法时doGet
post请求
- post方法是把提交的数据放在HTTP包的Body中
- 密文传递数据,数据量大,安全
- 效率相对没有GET高
- 对应的Servlet的方法时doPost
7.1.2request主要方法
方法名 | 说明 |
---|---|
String getParameter(String name) | 根据表单组件名称获取提交数据 |
void setCharacterEncoding(String charset) | 指定每个请求的编码 |
7.1.3request应用
HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1>欢迎你</h1>
<div>
<form action="HelloServlet" method="post">
<label>姓名:</label><input type="text" name="name"><br>
<label>年龄:</label><input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
Servlet代码
package com.zjl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取表单提交的姓名
String name = req.getParameter("name");
//获取年龄
String age = req.getParameter("ago");
//服务端输出打印
System.out.println(req.getRemoteAdd()+"发来信息:姓名"+name+"---->年龄:"+age);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.1.4get请求参数问题
产生乱码是因为服务器和客户端沟通的编码不一致造成的,因此解决办法是:在客户端和服务器之间设置一个统一的编码,之后就按照此编码进行数据的传输和接收
7.1.5get中文乱码
在Tomcat7及以下版本,客户端以UTF-8的编码传输数据到服务器端,而服务器短的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致因此才会产生中文乱码的。
- 解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。
- Tomcat8的版本中get方式不会出现乱码了,因为服务器对url的编码格式可以进行自动转换。
package com.zjl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Servlet implementation class HelloServlet
* 演示Servlet的GET请求,中文乱码的问题
*
*/
@WebServlet("/GETServlet")
public class GetServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取表单提交的姓名
String name = req.getParameter("name");
name=new String(name.getBytes("ISO8859-1"),"UTF-8");
//获取年龄
String age = req.getParameter("ago");
//服务端输出打印
System.out.println(req.getRemoteAdd()+"发来信息:姓名"+name+"---->年龄:"+age);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.1.6post中文乱码
由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收。
- 解决方案:使用ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行统一的编码设置。
package com.zjl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Servlet implementation class HelloServlet
* 演示Servlet的POST请求,中文乱码的问题
*
*/
@WebServlet("/POSTServlet")
public class PostServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void