Servlet原理解析&使用指南
Servlet(Server Applet)全称Java Servlet,是用Java编写的服务器端程序。广义上指任何实现了Server接口的类,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
Servlet的工作模式
客户端向服务器发送请求 服务器接收请求并启动相应的Servlet 服务器生成相应返回给客户端
Servlet_API
public interface Servlet
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
public abstract class HttpServlet extends GenericServlet
public class YourServlet extends HttpServlet
第一个Servlet
① 写一个Servlet实现类
可以直接实现Servlet接口,开发中一般继承HttpServlet抽象类
public class FirstServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//初始化Servlet
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//处理请求
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
//销毁Servlet
}
}
② 建立请求与服务的映射
如果没有建立映射关系,客户端无从请求该服务!在web.xml文件中servlet和servlet-mapping标签中添加相应的子标签来表达映射关系。
<servlet>
<servlet-name>服务名</servlet-name>
<servlet-class>完整Servlet实现类路径</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>服务名</servlet-name>
<url-pattern>/url请求名</url-pattern>
</servlet-mapping>
请求的大致过程:请求名 服务名 Servlet
url请求名是客户端的请求渠道
服务名是服务器端中服务的名字,对于客户端是透明的
一个服务可以对应多个请求
️ 请注意请求名的格式是否正确!否则Tomcat服务器启动失败。报错信息为:Error during artifact deployment. See server log for details.
️ <url-pattern>/login</url-pattern>
️ <url-pattern>/mytest/login</url-pattern>
<url-pattern>login</url-pattern>
<url-pattern>/*.jsp</url-pattern>
<url-pattern>/mytest/*.jsp</url-pattern>
一定要有 /
,一般仿照前两个正确案例命名即可,更多命名规则可以参考博文(点击此处)。
③ 测试案例
下面是配置文件的案例。在这个配置文件中我定义了一个请求名 /myTest 与实现类 FirstServlet 建立映射关系。
<?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">
<servlet>
<servlet-name>boringTest</servlet-name>
<servlet-class>com.java.webtest.FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>boringTest</servlet-name>
<url-pattern>/myTest</url-pattern>
</servlet-mapping>
</web-app>
- 在service()方法中写上一些测试代码,然后启动Tomcat服务器。在浏览器中输入地址和请求
http://localhost/myTest
NOTE 后就可以看到测试效果了。
Servlet容器
前文展示了Servlet的五个方法,也尝试写简单的请求。但是有一个问题没有讲清楚:客户只是发送了请求,但没有指导Servlet去执行哪个方法,这是为什么?其实中间还有一个没说的环节就是Servlet容器。Servlet接口是面向Servlet容器的,不是客户端。容器负责管理Servlet对象。
- 创建:容器只会给每个Servlet实现类创建一个对象,即单实例。
- 销毁:默认情况下,服务器在 第一次 接到客户端请求时容器会创建相应实例,并把对象留存到服务器关闭之前
- 调用:每次请求都会使容器调用Servlet对象的
service()
方法 - 数据传递:容器会封装客户端请求的详细信息为ServletRequest对象,服务器响应封装为ServletResponse对象。这两个对象都会传参给
service()
方法。请求对象和响应对象对后端开发比较友好,简化了操作。 - 监管:容器使用ServletContext封装应用的上下文环境详情,便于查看。
Servlet的生命周期
- 默认情况下Servlet第一次被请求时被创建,过程为:类加载 执行
init()
方法 执行service()
方法 service()
说明:如果你继承的是HttpServlet并直接继承了它实现的service()
,方法会判断客户端的请求方式,调用相应的doGet()
/doPost()
方法- 当服务器关闭时调取
destroy()
方法进行销毁
请求(ServletRequest)
HttpServletRequest
HttpServletRequest接口拓展了ServletRequest
常用方法
String
getParameter(String name)
从表单获取单值数据NOTEString[]
getParameterValues(String name)
从表单获取多值数据void
setCharacterEncoding(String charset)
指定每个请求的编码(仅对POST生效)RequestDispatcher
getRequestDispatcher(String path)
跳转并返回RequestDispatcher对象,该对象的forward()
方法用于转发请求,用法如下
request.getRequestDispatcher("../success.jsp").forward(request,response);
void
setAttribute(String key, Object value)
存值Object
request.getAttribute(String key)
取值,取出后需要强转类型
客户端发送数据 GET & POST
GET:不安全的提交方式,url地址栏可见 。直接参照百度搜索,例如搜索框中搜索关键字 嫦娥 后地址栏变为
https://www.baidu.com/s
?wd=嫦娥
&rsv_spt=1
&rsv_iqid=0xa2e58ae0001350d0
&issp=1
&f=8&rsv_bp=1
... ...
看见
?wd=嫦娥
了吗(我特意换行是为了展示清除,实际都是一行鸭)。可以提炼出基本格式网址.../请求名?key1=value1&key2=value2&key3=value3&...
GET提交方法:① 表单 ② a标签 ③ 手动地址栏拼接 ④ js提交
POST:相对安全的提交方式,url地址栏不可见 。通过前端页面提交POST表单
GET & POST 的区别:POST更安全、传输大小不限制,GET不安全、传输数据大小受URL长度限制限制
处理请求出现乱码(???????????)
设定字符集,仅对POST请求数据生效:
setCharacterEncoding("UTF-8")
对字符串转换字符集:
String s = new String(req.getParameter(key).getBytes("ISO-8859-1"),"GBK")
NOTE直接修改Tomcat的 server.xml 配置文件中的字符集NOTE
响应(ServletResponse)
HttpServletResponse
HttpServletResponse接口拓展了ServletResponse,声明了向客户端向客户端发送响应状态码、响应消息头、响应消息体的方法。
常用方法
void
addCookie(Cookie var1)
给这个响应添加一个cookievoid
sendRedirect(String var1)
发送一条响应码,将浏览器跳转到指定的位置PrintWriter
getWriter()
获得流对象,再调用对象的write()
方法向响应页面中写入内容NOTEvoid
setContentType(String var1)
设置响应内容的类型
转发和重定向
跳转页面有转发和重定向两种方式。
req.sendRedirect(url)
重定向见名知意,是指让客户端重新定向。完整的重定向过程:
1️⃣ 客户端第一次请求
2️⃣ 服务器得到请求并返回一个URL
3️⃣ 客户端使用第一次返回的URL进行第二次请求
4️⃣ 服务器得到请求并返回“最终结果” NOTE
重定向需要客户端两次请求,转发只需要客户端一次请求,请求的处理在服务器端就完成了。
区别:重定向会导致request丢失(第一次的HttpServletRequest请求对象),而转发不会,因为转发使用了.forward(req,resp)
方法传递了请求对象。
会话(session)
HttpRequest对象可以存值,但是在重定向后HttpRequest对象丢失,其中的数据也随之丢失。很多时候需要一个更持久的对象来存值,可以使用session对象。会话概念:从打开浏览器到关闭浏览器,期间访问服务器就称为一次会话。
HttpSession
获取session对象:
ServletRequest接口定义了获取方法
HttpSession
getSession()
,在ServletRequest对象上调用得到一个会话对象session = req.getSession()
。
HttpSession的常用方法
void
setAttribute(String key,Object value)
存值Object
getAttribute(String key)
取值void
removeAttribute(String key)
移除值String
getId()
获取session的id,id是服务器判定是否是同一次会话的依据void
setMaxInactiveInterval(int interval)
设置session的非活动时间NOTE(单位:秒)NOTEint
getMaxInactiveInterval()
获取session的非活动时间(单位:秒),默认为30分钟void
invalidate()
终止session,使session失效
获得初始化参数
通过req.setCharacterEncoding("utf-8")的方式设置字符集的方式不便于后期维护和修改,可以通过初始化参数实现
web.xml 定义初始化参数
Servlet级始化参数
web.xml 文件中定义servlet标签子标签init-param
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
在Servlet初始化方法init()中加入代码获取初始化参数
@Override
public void init(ServletConfig config) throws ServletException {
encoding= config.getInitParameter("encoding");
...
}
全局初始化参数
web.xml 文件中定义与servlet标签同级的context-param标签
<context-param>
<param-name>globalEncoding</param-name>
<param-value>utf-8</param-value>
</context-param>
获取初始化参数
@Override
public void init(ServletConfig config) throws ServletException {
bianhao=config.getServletContext().getInitParameter("globalEncoding");
...
}
用@WebServlet配置Servlet
前面在配置文件中建立映射和其他参数的步骤比较麻烦。Servlet 3.0用注解解决了这个问题。
Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。
@WebServlet 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。
常用属性
属性 | 类型 | 说明 |
---|---|---|
asyncSupported | boolean | 是否支持异步操作模式 |
displayName | String | Servlet显示名称 |
initParams | webInitParam[] | 配置初始化参数 |
loadOnStartup | int | 容器加载Servlet的优先级(默认值0,在请求时加载) |
name | String | 指定Servlet名称 |
urlPatterns / value | String[] | 指定Servlet处理的url |
使用案例
/**
* 初始化参数注入后的使用方式与前面在web.xml中定义后的使用方式完全相同
* 其他参数注入后的效果也和在web.xml中定义的效果相同
* 使用注解注解注入配置更方便开发
* urlPatterns是String[]类型,可以配置多个映射,例如{"/user/test" , "/user/example"}
*/
@WebServlet(
name = "myUserServlet",
urlPatterns = {"/user/test"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name="name", value="小明"),
@WebInitParam(name="pwd", value="123456")
}
)
public class UserServlet implements HttpServlet {
...
}
如有文章错误或困惑之处欢迎评论指出,我会尽快改正和回复。
最新文章
- Leetcode2:Add Two Numbers@Python
- 如何用Tacker将NFV带入OpenStack?
- 七牛php sdk 生成上传凭证时出现 undefined function Qiniu_SetKeys()
- 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制
- 【poj3017】 Cut the Sequence
- Mysql基础2
- JS 对象属性相关--检查属性、枚举属性等
- 模块已加载,但对dllregisterServer的调用失败
- css3技巧——产品列表之鼠标滑过效果(一)
- MVC神韵---你想在哪解脱!(十三)
- 50道经典的JAVA编程题(31-35)
- 在Amazon AWS RHEL 7上安装 配置PPTP VPN
- Grunt + Bower—前端构建利器
- 【iOS】UIViewController基类的实现
- 使用spring中4.2.6版本使用@Value取值失败,结果为${xxx}的情况
- MyBatis映射文件4(参数获取#{}和${}/select标签详解[返回类型为list])
- python框架之Flask(1)-Flask初使用
- proto 2 语法
- c++ vector常见用法
- leveldb skiplist的改编非并发去除内存池版本 代码练习
热门文章
- 使用DTK创建模糊背景窗口并自定义阴影效果
- WSL (Windows Subsystem for Linux) 的 VSLAM (Visual Simultaneous Localization and Mapping) 道路
- Java之浅拷贝和深拷贝
- five86-1 (OpenNetadmin RCE+cp命令提权+crunch生成密码字典)
- CS144学习(2)TCP协议实现
- 修改jupyter-notebook的python3版本
- Trailing commas
- React Security Best Practices All In One
- TypeScript &; LeetCode
- LeetCode &; tree &; binary tree