Servlet
一、Servlet简介
1. 什么是Servlet
Servlet是Server Applet的简称,称为服务器小程序 或 小服务程序
Servlet是一个Java程序,是在服务器上运行以处理客户端请求并做出响应的程序
该Java程序必须符合特定的规范要求,称为Servlet规范
2. Servlet规范
制定Servlet相关标准的规范
要求:
- 一个Servlet就是一个Java类,一般都继承自HttpServlet类 或 实现Servlet接口
- Servlet必须由Servlet容器来执行,Servlet容器一般存在于Web服务器或应用服务器中,称为Servlet服务器
版本:Servlet 2.5、3.0、4.0
3. Servlet服务器
符合Servlet规范,能够运行Servlet的服务器,称为Servlet服务器/Servlet容器/Web服务器/Web容器
最常见的就是tomcat
二、Tomcat
1. Tomcat简介
Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目
是一个开源的、免费的、符合Servlet规范的Web服务器
版本:Tomcat 6、7、8、9、10
2. 安装tomcat
步骤:
-
下载安装包
从tomcat官网下载安装包,这里使用apache-tomcat-7.0.93.zip
-
解压安装包
将安装包解压到无中文、无空格的路径下,无需安装
解压后目录下的内容:
bin // 可执行程序、命令 conf // 配置文件,核心配置文件server.xml lib // 运行web程序所需的各种jar文件 logs // 运行日志 temp // 临时文件 webapps // 存放Web应用,网站发布的目录 work // 由jsp文件生成的java文件以及对应的class文件
-
配置环境变量
tomcat依赖于Java环境变量,如 JAVA_HOME、CLASSPATH
tomcat环境变量的配置:
- 添加CATALINA_HOME变量,值为tomcat解压后的目录路径
- 修改PATH变量,添加tomcat的bin目录路径
-
启动tomcat
启动:
startup.bat
停止:
shutdown.bat
访问:http://localhost:8080 (Tomcat默认使用8080端口,在conf/server.xml中可以修改端口)
3. 目录结构
Web应用的目录结构如下:
|-Web应用名称 // Web应用的根目录
|-WEB-INF // 存放各种资源,该目录中文件不能直接访问
|-classes // 存放class文件
|-lib // 存放jar包
|-web.xml // 核心配置文件,称为部署描述文件
|-自定义目录 // 存储网站的相关资源,不能直接访问,安全性较高
|-自定义目录 // 存放网站的相关资源,可以直接访问,如html、css、js、image等
手动部署Web应用,步骤:
- 在tomcat的webapps目录下创建对应的目录结构
- 配置网站的资源
- 配置web.xml
- 启动tomcat,访问
http://localhost:8080/Web应用名
4. 集成Tomcat
在IDEA中集成Tomcat,步骤:
点击右上角的下拉箭头,选择"Edit Configurations"——>Add New Configuration(+)——>Tomcat Server——>Local
- Name:自定义名称,随意取,如:tomcat7
- Server/Application Server:选择tomcat所在目录
- Deployment/Add(+)/Artifact:选择要部署的项目
- Application context:指定部署访问的名称
- On ‘Update’ action:Update classes and resources // 当用户主动执行更新的时候更新
- On frame deactivation: Update classes and resources // 当编辑窗口失去焦点时更新
- windows控制台输出默认gbk,可以在idea设置tomcat中的VM options填上-Dfile.encoding=UTF-8
部署目录:
-
IDEA默认将Web应用发布到out/artifacts目录下,部署位置并不在tomcat/webapps目录下,是通过tomcat的虚拟目录路径实现的
-
查看:Project Structure——>Artifacts——>Output directory (Web工程的部署输出目录)
**注:**修改java代码后需要重启tomcat才生效
三、开发Servlet
1. 基于配置文件
步骤:
-
添加依赖
Project Structure——>Modules——>Dependencies——>Add(+)——>Library——>Application Server Libraries——>Tomcat
-
创建Servlet
创建一个类,继承自HttpServlet类
public class HelloServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("接收到客户端的请求。。。。"); response.setContextType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<h1 style='color:red;'>您的请求已接收到。。。。</h1>"); out.close(); } }
-
配置Servlet
编辑web.xml文件
<servlet> <!--指定Servlet名称,可自定义--> <servlet-name>HelloServlet</servlet-name> <!--指定Servlet类的全名--> <servlet-class>com.itany.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <!--指定映射的Servlet名称--> <servlet-name>HelloServlet</servlet-name> <!--指定访问该Servlet的url,以正斜杠开头--> <url-pattern>/hello</url-pattern> </servlet-mapping>
2. 基于注解
Servlet 3.0之后可以通过注解配置Servlet(Servlet3.0对应的是JavaEE6)
// @WebServlet(urlPatterns="/world")
@WebServlet("/world")
public class WorldServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
out.println("<html>");
out.println(" <head>");
out.println(" <title>Title</title>");
out.println(" </head>");
out.println(" <body>");
out.println(" 你好,欢迎来到Servlet世界");
out.println(" </body>");
out.println("</html>");
out.close();
}
}
3. 通配符
在配置url-pattern时,可以使用通配符*
来匹配任意字符
/aa/*
表示只要以/aa/
开头都可以,如/aa/bb
、/aa/cc/dd
等*.do
表示只要以.do
结尾都可以,如aa.do
、bb.do
等**(该方式在配置时前面不能加 / 正斜杠)**
四、Servlet详解
1. 运行流程
流程:
-
客户端浏览器向服务器发送请求
-
服务器根据web.xml配置 和 注解配置 找到匹配的Servlet,并自动调用service()方法
-
服务器会创建一个请求对象HttpServletRequest,其中包含了请求时传递的参数信息
服务器会创建一个响应对象HttpServletResponse,用来响应客户端
-
HttpServletRequest和HttpServletResponse对象会作为参数传给service()方法
-
通过service()方法来实现业务处理,完成后通过响应对象向客户端响应结果
-
客户端浏览器展示结果
2. HttpServletRequest
常用方法:
方法名 | 含义 |
---|---|
String getParameter(String name) | 获取请求中参数 |
String[] getParameterValues(String name) | 获取请求中参数,返回数组,一般用于获取复选框的值 |
String getContextPath() | 获取上下文路径,即Web应用名 |
String getServletPath() | 获取Servlet路径,即浏览器地址栏应用名后面的路径 |
String getMethod() | 获取请求的方式 |
String getRemoteAddr() | 获取访问者的ip地址 |
RequestDispatcher getRequestDispatcher(String path) | 获取请求转换器,转发到指定的资源 |
void setCharacterEncoding(String encoding) | 设置请求的字符编码 |
3. HttpServletResponse
常用方法:
方法 | 含义 |
---|---|
PrintWriter getWriter() | 获取打印流,向客户端响应结果 |
void sendRedirect(String location) | 重定向到指定的资源 |
void setContentType(String type) | 设置响应的内容类型和编码 |
4. 页面跳转
两种方式:
-
重定向
response.sendRedirect("地址")
-
转发
request.getRequestDispatcher("地址").forward(request,response)
对比:
重定向 | 转发 |
---|---|
地址栏发生了改变 | 地址栏没有发生改变 |
浏览器重新发送了一个新的请求 | 没有产生新的请求,属于服务器内部控制权的转移 |
无法访问WEB-INF下的资源 | 可以访问WEB-INF下的资源 |
不共享请求与响应 | 转发所涉及的所有组件共享请求与响应 |
应用场合:
- 执行更新操作(增删改)时建议使用重定向,避免刷新页面时再次执行相同的操作
- 执行查询操作时,一般使用转发
5. 路径问题
绝对路径:
- 以
/
开头的路径,表示的是从地址栏的端口号后面开始查找 - 转发时的绝对路径,表示的是从地址栏的应用名后面开始查找
相对路径:
- 不以
/
开头的路径,表示的是从地址栏的最后一层路径的位置开始查找 - 会将最后一层路径替换成所写的相对路径
- 相对路径在查找时比较麻烦,容易混乱,开发中不建议使用
6. 乱码问题
6.1 请求乱码
获取请求中的数据时出现乱码,根据请求方式的不同,解决乱码的方法也不一样
-
post
request.setCharacterEncoding("编码")
-
get
tomcat内部默认使用ISO8859-1编码解析数据,所以会出现乱码(在tomcat 8及以上版本中默认使用的是UTF-8)
方法一:
name = new String(name.getBytes("ISO8859-1"),"UTF-8")
先使用ISO8859-1编码,再使用UTF-8解码
方法二:
修改tomcat默认使用的编码
编辑server.xml文件,添加
URIEncoding="编码"
配置<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
6.2 响应乱码
响应数据时出现乱码,解决方法:response.setContentType(text/html;charset=utf-8);
五、Servlet生命周期
共分为4个阶段:实例化——>初始化——>请求处理——>销毁
1. 实例化
Servlet实例并不是使用者创建的,而是由服务器自动创建,且只会实例化一次
默认情况下当第一次访问Servlet时才会加载实例化Servlet
设置服务器启动时就加载,两种方式:
-
基于配置文件
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.itany.servlet.HelloServlet</servlet-class> <!-- 设置服务器启动时加载Servlet,值是一个数字,表示加载顺序,数字越小,优先级越高 --> <load-on-startup>2</load-on-startup> </servlet>
-
基于注解
@WebServlet(urlPatterns = "/hello",loadOnStartup = 1)
注:从结构上来看,Servlet并不是单例结构,但Web容器只会实例化一次,表现出单例的效果
2. 初始化
当Servlet实例化时会自动调用init()方法,执行初始化操作,且只执行一次
配置Servlet初始化参数:
-
基于配置文件
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.itany.servlet.HelloServlet</servlet-class> <!-- 配置当前Servlet的初始化参数,可以配置多个参数 --> <init-param> <param-name>username</param-name> <param-value>admin</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>123</param-value> </init-param> </servlet>
-
基于注解
/* * @initParams 配置初始化参数,值使用大括号{}括起来,表示一个数组 * @WebInitParam 表示一个初始化参数的配置 */ @WebServlet(urlPatterns = "/hello",initParams = { @WebInitParam(name="username",value="admin"), @WebInitParam(name="password",value="123") })
获取Servlet初始化参数:
@Override
public void init() {
String username = getInitParameter("username");
String password = getInitParameter("password");
System.out.println(username + "----" + password);
}
配置Servlet上下文参数,全局的参数:
<web-app>
<context-param>
<param-name>name</param-name>
<param-value>tom</param-value>
</context-param>
</web-app>
获取Servlet上下文参数:
String name = getServletContext().getInitParameter("name");
3. 请求处理
每次访问Servlet时都会自动调用该Servlet中的service()方法或doXxx()方法,完成业务处理并响应结果
- 一般会重写service()方法或doXxx()方法
- 如果重写service()方法,则会调用service()方法
- 如果重写doXxx()方法,则会根据请求方式的不同调用对应的doXxx()方法,如doGet()、doPost()等
4. 销毁
当服务器正常关闭时,会自动调用destroy()销毁方法
六、HTTP请求信息
1. 简介
浏览器向服务器发送请求时,会封装一个请求报文,向服务器发送请求信息
服务器响应时,会封装一个响应报文,向客户端响应信息
2. 请求报文
一个HTTP请求报文由三部分组成:请求行、请求头、请求体
-
请求行
Request URL: https://www.baidu.com/s?wd=java // 请求URL地址 Request Method: GET // 请求方法,如GET、POST、DELETE、PUT等
-
请求头 Request Headers
User-Agent // 客户端使用的浏览器类型 Accept // 客户端可识别的内容类型列表 Host // 服务器主机地址
-
请求体 Request Body
如果是get请求,通过查询字符串提交数据 Query String Parameters 如果是post请求,通过请求体提交数据
3. 响应报文
一个HTTP响应报文也由三部分组成:响应行、响应头、响应体
-
响应行
Status Code: 200 OK
HTTP状态码表示服务器处理HTTP请求的状态,常见状态码:
状态码 英文名称 中文含义 200 OK 请求成功,服务器响应正常 302 Found 资源被重定向 400 Bad Request 客户端请求的语法错误,服务器无法理解 401 Unauthorized 请求要求用户的身份认证 403 Forbidden 服务器拒绝执行此请求,如权限不足 404 Not Found 请求的资源不存在 405 Method Not Allowed 请求的方式不对 500 Internal Server Error 服务器内部异常 502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 503 Service Unavailable 由于超载或系统维护,服务器暂时无法处理客户端的请求 -
响应头 Response Header
Allow:服务器支持哪些请求方法(如GET、POST等) Content-Length:表示内容的长度 Content-Type:表示内容的MIME类型
-
响应体 Response Body
响应体就是响应的消息体,如果是纯数据就是返回纯数据,如果请求的是HTML页面,那么返回的就是HTML代码,如果是JS就是JS代码,如此之类。
七、练习:用户管理系统
User Management System(UMS)
功能:
- 显示用户列表
- 添加用户
- 修改用户
- 删除用户
t_user 用户表
id 编号
name 姓名
pwd 密码
age 年龄
hobby 爱好
info 简介
sex 性别
idea的jar包手动导入
方式一:适合少量jar包的导入
–1–右键工程-open module settings(F4)-modules-Dependencies-±JARs or directories
方式二:适合于大量jar包,通过自定义建立公用库的内容,重复引用相关jar包时可减少操作
–1–右键工程-open module settings(F4)-library-创建library-往创建的library中添加jar包-点击modules-Dependencies-library(选择刚才自己建立的library)