java-servlet的学习
java-servlet的学习
Jin概念
Servlet含义是服务器端的小程序 在整个Web应用中,Servlet主要负责处理请求、协调调度功能。我们可以把Servlet称为Web应用中的控制器
具体功能:
- 接收请求
- 处理请求(调用业务逻辑 service 方法)
- 分发页面(转发重定向)
- 返回响应
生命周期
servlet 的生命周期:
- 创建对象:第一次请求和修改Web应用启动时,只会经历一次
- 初始化:创建对象后,调用方法
init(ServletConfig servletConfig)
,只会经历一次 - 处理请求 :接收到请求后,调用方法
service(ServletRequest servletRequest, ServletResponse servletResponse)
,会经历多次 - 清理操作:Web应用卸载之前,调用方法
destroy()
,只会经历一次
总结: Servlet 第一次接收请求时,会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service()),从接收第二次请求开始,每一次都是服务
默认情况下:Servlet在第一次接收到请求的时候才创建对象,不过可修改 servelt 创建对象的时机
修改方法:修改web.xml 配置文件的 Servlet配置
<servlet>
<!-- 配置名称 -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置全类名 -->
<servlet-class>com.example.servlet.HelloServlet</servlet-class>
<!-- 配置启动顺序 -->
<load-on-startup>1</load-on-startup>
</servlet>
HttpServlet和Servlet继承关系
创建Servlet
首先导入依赖
两种创建方法:
实现 Servlet 接口
继承 HttpServlet 类
实现 Servlet 接口 ,对应生命周期方法
@WebServlet("/hello")
public class HelloServlet implements Servlet {
// 初始化方法
@Override
public void init(ServletConfig servletConfig) throws ServletException {}
// 每次servlet被访问 调用该方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello servlet");
}
// ServletConfig 对象
@Override
public ServletConfig getServletConfig() {return null;}
// 获取 Servlet 信息
@Override
public String getServletInfo() {return null;}
// servlet 销毁调用的方法
@Override
public void destroy() {}
}
继承 HttpServlet 重写 doGet, doPost等方法
根据你的请求方法,调用不同的 doXXX 方法
Servlet 和 HttpServlet关系图
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
// 重写 doGet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.printIn("git 请求");
}
// 重写 doPost
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.printIn("post 请求");
}
}
request 和 response 对象
- request就是将请求文本封装而成的对象,所以通过request能获得请求文本中的所有内容,请求头、请求体、请求行 。常用来获取客户端传过来的参数信息。转发请求到另一个地址
- 客户端请求后响应请求的对象,通常可设置响应头,实现页面重定向,定时刷新,设置cookie等功能
访问路径配置
两种方法:
注解 @WebServlet
xml配置文件
@WebServlet
- name:Servlet的名称,默认为该类的简单类名;
- value/urlPatterns:定义Servlet处理的请求URL模式;
- loadOnStartup:指示Servlet容器在应用程序启动时是否预加载Servlet;
- initParams:Servlet初始化参数;
- description:Servlet描述信息;
- asyncSupported:表明该Servlet是否支持异步操作。
通过注解配置访问路径 如 @WebServlet(“\hello”) 通过访问项目地址+ \hello 访问
可配置多路径 如 @WebServlet(urlPatterns={“/hello1”, “hello2”})
支持通配符 *
配置 如 @WebServlet(“/hello/* “),@WebServlet(“ *.do “)
web.xml
<!-- 配置 servlet 信息 -->
<servlet>
<!-- 配置名称 -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置全类名 -->
<servlet-class>com.example.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 配置 servlet 路径 -->
<servlet-mapping>
<!-- 找到上面配置的 servlet 名称,配置上对应的路径-->
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
ServletConfig与ServletContext
类比
ServletConfig
可直接通过方法getServletConfig()获取,它在Servlet初始化的时候被创建,通过这个对象我们可以获取到servletName,ServletContext对象,初始化参数等
ServletConfig 接口
方法 | 描述 |
---|---|
getServletName() | 获取 servlet-name 标签定义的名字 |
getServletContext() | 获取 ServletContext 对象 |
getInitParameter() | 获取配置Servlet时设置的『初始化参数』,根据名字获取值 |
getInitParameterNames() | 获取所有初始化参数名组成的Enumeration对象 |
代码举例
// 配置 初始化参数
@WebServlet(urlPatterns = "/hello",initParams = {
@WebInitParam(name = "encoding", value = "UTF8"),
@WebInitParam(name = "hello", value = "world")
})
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取 servletConfig 对象
ServletConfig servletConfig = this.getServletConfig();
// 获取初始化参数
String encoding = servletConfig.getInitParameter("encoding");
String hello = servletConfig.getInitParameter("hello");
System.out.println(encoding);
System.out.println(hello);
// 获取所有初始化参数名
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
// 拿到每一个参数名
String name = initParameterNames.nextElement();
System.out.println("name = " + name);
// 通过拿到的参数名获取对应的 value
String initParameter = servletConfig.getInitParameter(name);
System.out.println("value = "+initParameter);
}
}
}
配置 初始化参数 方法2 xml配置文件
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.example.servlet.TestServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>hello</param-name>
<param-value>world</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
ServletContext
代表:整个Web应用。ServletContext对象的生命周期和整个Web应用的生命周期一致
ServletContext对象的作用:
- 有了ServletContext对象,就可以共享从应用程序中的所有资源访问到的数据信息,并且可以动态注册web对象
- 可以获得应用域的全局初始化参数,以及达到Servlet之间的数据共享
- 可以作为域对象在整个应用中共享数据;域对象即在一定的作用范围内实现资源共享
- 可以用来获取应用中的资源在服务器上的绝对路径
- 获取文件的mime类型: 在网络传输中,并不是以扩展名来区分文件的类型,都是以mime类型;如:text/html;表示一个html文件
域对象
在Servlet规范中,一共有4个域对象。request请求域,PageContext页面域,session会话域,application应用域。ServletContext就是其中的一个。是web应用中最大的作用域,也叫application应用域,可以实现整个应用之间的数据共享
常用方法:
- getRealPath():获取某个资源的真实路径
- getInitParameter(): 获取整个Web应用级别的初始化参数
- setAttribute() / getAttribute():Web应用范围的域对象存入/取出对象
Web应用级别的初始化参数
<!-- 配置Web应用的初始化参数 -->
<context-param>
<param-name>handsomeMan</param-name>
<param-value>alsoMe</param-value>
</context-param>
获取方法
String handsomeMan = servletContext.getInitParameter("handsomeMan");
System.out.println("handsomeMan = " + handsomeMan);
和 init-param
区别
<init-param>
是放在一个servlet内的,所以这个参数是只针对某一个servlet而言的
所以他们的区别就有点像全局变量和和局部变量的<context-param>
是针对整个项目,所有的servlet都可以取得使用,<init-param>
只能是在那个servlet下面配置,就在那个servlet里面调用
转发和重定向
转发
转发定义 在请求的处理过程中,Servlet完成了自己的任务,需要把请求转交给下一个资源继续处理
关键:由于转发操作的核心部分是在服务器端完成的,所以浏览器感知不到,整个过程中浏览器只发送一次请求
request.getRequestDispatcher("/转发的地址").forward(request, response);
重定向
定义:在请求的处理过程中,Servlet完成了自己的任务,然后以一个响应的方式告诉浏览器:要完成这个任务还需要你另外再访问下一个资源
代码
response.sendRedirect("/重定向的地址");
关键:由于重定向操作的核心部分是在浏览器端完成的,所以整个过程中浏览器共发送两次请求
转发和重定向的应用场景
可以简单的判断:能用转发的先用转发,如果转发不行,再使用重定向。
- 需要通过同一个request对象把数据携带到目标资源:只能用转发
- 如果希望前往下一个资源之后,浏览器刷新访问的是第二个资源:只能用重定向
请求参数
获取请求参数的常用方法
方法 | 描述 |
---|---|
Map<String, String[]> request.getParameterMap() | 获取包含全部请求参数的Map |
String request.getParameter(“请求参数的名字”) | 获取参数名称对应的值 |
String [] request.getParameterValues(“请求参数的名字”) | 获取参数名称对应的值,常用对 checkbox 提交的数据 |
Enumeration |
获取所有参数名组成的Enumeration对象 |
请求响应设置字符集
设置字符集避免乱码问题
post 请求,在处理请求的方法里写在最前面
// 使用request对象设置字符集
request.setCharacterEncoding("UTF-8");
get 新版本内部处理好了
响应设置
response.setCharacterEncoding("UTF-8");
PrintWriter writer = response.getWriter();
writer.write("hello world!");
Session 会话
客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端下次客户端给服务器发请求时,会把 sessionID 带给服务器,服务器就能获取到,就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端
常用方法
方法 | 描述 |
---|---|
request.getSession() | 获取当前的会话,没有则创建一个新的会话 |
request.getSession(true) | 效果和不带参数相同 |
request.getSession(false) | 获取当前会话,没有则返回null,不会创建新的 |
session.getId() | 获取sessionID |
session.isNew() | 判断当前session是否是新的 |
ession.getMaxInactiveInterval() | 获取 session的非激活间隔时长,默认1800秒 |
session.setMaxInactiveInterval() | 设置 session的非激活间隔时长 |
session.invalidate() | 强制性让会话立即失效 |
session保存作用域
session保存作用域是和具体的某一个session对应的
区分其他作用域
- request:一次请求响应范围
- session:一次会话范围有效
- application: 一次应用程序范围有效
常用的API:
- void session.setAttribute(k,v):向当前会话存储数据
- Object session.getAttribute(k):根据 key 向当前会话获取数据
- void removeAttribute(k) :根据 key 向当前会话移除数据
代码举例
public class HelloWorldServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.通过request对象获取session对象
HttpSession session = request.getSession();
// 2.设置数据名称和数据的值
String attrName = "sessionHelloAttrName";
String attrValue = "sessionHelloAttrValue";
// 3.将数据存入会话域
session.setAttribute(attrName, attrValue);
}
}
Cookie
cookie 概念
在浏览器端临时存储数据
键值对
键和值都是字符串类型
数据量很小
没有 cookie: 在服务器端没有创建Cookie并返回的情况下,浏览器端不会保存Cookie信息。双方在请求和响应的过程中也不会携带Cookie的数据
创建和读取
创建 cookie 返回
// 1.创建Cookie对象
Cookie cookie = new Cookie("cookie-message", "hello-cookie");
// 2.将Cookie对象添加到响应中
response.addCookie(cookie);
// 3.返回响应
processTemplate("page-target", request, response);
浏览器拿到Cookie之后,以后的每一个请求都会携带Cookie信息
读取 cookie
// 1.通过request对象获取Cookie的数组
Cookie[] cookies = request.getCookies();
// 2.遍历数组
for (Cookie cookie : cookies) {
System.out.println("cookie.getName() = " + cookie.getName());
System.out.println("cookie.getValue() = " + cookie.getValue());
}
Cookie的时效性
会话级Cookie:默认情况
- 保存在浏览器的内存里,在浏览器关闭时会被释放
持久化Cookie:
- 服务器端调用Cookie的setMaxAge(以秒为单位的存活时间)方法
- 存活时间正数:还能够存活的秒数
- 存活时间为零:告诉浏览器立即删除这个Cookie
- 存活时间为负:告诉浏览器这个Cookie是一个会话级Cookie
- 服务器把这个Cookie返回给浏览器时就等于通知浏览器:这个Cookie还能存在多长时间
给Cookie设置过期时间
// 正数:Cookie的过期时间,以秒为单位
// 负数:表示这个Cookie是会话级的Cookie,浏览器关闭时释放
// 0:通知浏览器立即删除这个Cookie
cookie.setMaxAge(20);
domain和path
上网时间长了,本地会保存很多Cookie。对浏览器来说,访问互联网资源时不能每次都把所有Cookie带上。浏览器会使用Cookie的domain和path属性值来和当前访问的地址进行比较,从而决定是否携带这个Cookie。
- domain:表示这个Cookie属于哪个网站,通常以域名为值
- path:表示这个Cookie属于网站下的哪一个具体的资源
filter 过滤器
过滤器三要素
- 拦截:把请求拦截下来才能够做后续的操作
- 过滤:业务代码处理
- 放行:让请求继续去访问它原本要访问的资源
使用步骤
- 实现javax.servlet.Filter接口
- 在 doFilter()方法执行过滤
- 处理完:chain.doFilter(request, response)放行,或者进行重定向或转发
代码
@WebFilter("*.do")
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("helloA");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("helloA2");
}
@Override
public void destroy() {}
}
配置 filter url 像servlet 一样可以采用注解和 web.xml 配置文件
可配置通配符,例如 @WebFilter(“*.do”)表示拦截所有以 .do 结尾的请求
xml配置
<filter>
<!-- 配置Filter的名称 -->
<filter-name>HelloFilter</filter-name>
<!-- 配置Filter的全类名,便于Servlet容器创建Filter对象 -->
<filter-class>com.example.filter.HelloFilter</filter-class>
</filter>
<!-- 配置Filter要拦截的目标资源 -->
<filter-mapping>
<!-- 指定这个mapping对应的Filter名称 -->
<filter-name>HelloFilter</filter-name>
<!-- 通过请求地址模式来设置要拦截的资源 -->
<url-pattern>/HelloFilter</url-pattern>
</filter-mapping>
多个 filter 执行顺序
- 注解的方式进行配置:按照全类名字母排序执行
- xml的方式进行配置:按照配置文件的顺序
生命周期
生命周期环节 | 调用的方法 | 时机 | 次数 |
---|---|---|---|
创建对象 | 无参构造器 | 默认:Web应用启动时 | 一次 |
初始化 | init(FilterConfig filterConfig) | 创建对象后 | 一次 |
处理请求 | doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 接收到请求后 | 多次 |
清理操作 | destroy() | Web应用卸载之前 | 一次 |
监听器
概念
Servlet监听器:Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext,HttpSession 和HttpServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件
监听对象:
ServletContext:application,整个应用只存在一个
HttpSession:session,针对每一个对话
ServletRequest:request,针对每一个客户请求
监听内容:创建、销毁、属性改变事件
监听作用:可以在事件发生前、发生后进行一些处理,一般可以用来统计在线人数和在线用户、统计网站访问量、系统启动时初始化信息等。
分类
监听域对象本身
- ServletContext
- HttpSession
- HttpServletRequest
监听域对象的属性域
- 应用域
- 会话域
- 请求域
监听存入Session域的对象本身
- 对象是否存入会话域
- 对象是否和Session一起被钝化到了硬盘上
监听器列表
对象的创建与销毁
ServletContextListener
作用:监听ServletContext对象的创建与销毁
方法名 | 作用 |
---|---|
contextInitialized(ServletContextEvent sce) | ServletContext创建时调用 |
contextDestroyed(ServletContextEvent sce) | ServletContext销毁时调用 |
ServletContextEvent对象代表从ServletContext对象身上捕获到的事件,通过这个事件对象我们可以获取到ServletContext对象
HttpSessionListener
作用:监听HttpSession对象的创建与销毁
方法名 | 作用 |
---|---|
sessionCreated(HttpSessionEvent hse) | HttpSession对象创建时调用 |
sessionDestroyed(HttpSessionEvent hse) | HttpSession对象销毁时调用 |
HttpSessionEvent对象代表从HttpSession对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpSession对象
ServletRequestListener
作用:监听ServletRequest对象的创建与销毁
方法名 | 作用 |
---|---|
requestInitialized(ServletRequestEvent sre) | ServletRequest对象创建时调用 |
requestDestroyed(ServletRequestEvent sre) | ServletRequest对象销毁时调用 |
ServletRequestEvent对象代表从HttpServletRequest对象身上捕获到的事件,通过这个事件对象我们可以获取到触发事件的HttpServletRequest对象。另外还有一个方法可以获取到当前Web应用的ServletContext对象
属性创建、修改和销毁
ServletContextAttributeListener
作用:监听ServletContext中属性的创建、修改和销毁
方法名 | 作用 |
---|---|
attributeAdded(ServletContextAttributeEvent scab) | 向ServletContext中添加属性时调用 |
attributeRemoved(ServletContextAttributeEvent scab) | 从ServletContext中移除属性时调用 |
attributeReplaced(ServletContextAttributeEvent scab) | 当ServletContext中的属性被修改时调用 |
ServletContextAttributeEvent对象代表属性变化事件,它包含的方法如下
方法名 | 作用 |
---|---|
getName() | 获取修改或添加的属性名 |
getValue() | 获取被修改或添加的属性值 |
getServletRequest () | 获取触发事件的ServletRequest对象 |
HttpSessionBindingListener
作用:监听某个对象在Session域中的创建与移除
方法名 | 作用 |
---|---|
valueBound(HttpSessionBindingEvent event) | 该类的实例被放到Session域中时调用 |
valueUnbound(HttpSessionBindingEvent event) | 该类的实例从Session中移除时调用 |
HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:
方法名 | 作用 |
---|---|
getName() | 获取当前事件涉及的属性名 |
getValue() | 获取当前事件涉及的属性值 |
getSession() | 获取触发事件的HttpSession对象 |
HttpSessionActivationListener
作用:监听某个对象在Session中的序列化与反序列化。
方法名 | 作用 |
---|---|
sessionWillPassivate(HttpSessionEvent se) | 该类实例和Session一起钝化到硬盘时调用 |
sessionDidActivate(HttpSessionEvent se) | 该类实例和Session一起活化到内存时调用 |
HttpSessionEvent对象代表事件对象,通过getSession()方法获取事件涉及的HttpSession对象
简单举例:监听ServletContext对象的创建与销毁
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("Servlet上下文对象初始化动作被我监听到了....");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("Servlet上下文对象销毁动作被我监听到了.....");
}
}
配置添加 @WebListener 或配置xml文件
<listener>
<listener-class>com.example.listener.MyServletContextListener</listener-class>
</listener>
参考资料