$1 Servlet
![image-20220523152958194]
1.1 Servlet 的基本概念
Servlet是运行在服务器上面用于生成动态web页面的程序
1.1.1 Servlet编程
基本关系:
servlet为一个结构,通过GenericServlet或者HttpServlet实现
/*Servlet接口中的函数
ServletConfig:用于保存Servlet实例中配置信息
ServletContext:提供有关的容器信息
*/
public void init(ServletConfig config) throws ServeletException;
public void service(ServeletRequest req,ServletResponese res) throws ServletException,IOException;
public void destroy();
public ServletConfig getServletConfig();
public String getServletInfo(); //包含servlet信息
/*GenericServlet*/
/*
该类对于Servlet接口中的大多数方法进行了实现,但是在service方法中的设置为abstract,所以该方法为一个抽象类,对于一个程序,我们只需要实现其service方法就可以对于一个用户的请求进行处理并且返回对应的响应
*/
/*HttpServlet*/
/*
该类对于GenericServlet进行了集成,并且对于servlet提供的接口进行了HTTP实现,对service方法作为了分发器!!!!任何时候不可重载
*/
/*常用方法doGet(),doPost(),doHead(),doOptions(),doDelete(),doPut(),doTrace()*/
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServeletException;
/*实例*/
package Hello;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Servlet implementation class HelloWorld
*/
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter o=response.getWriter();
o.println("<html>");
o.println("<body>");
o.println("<head>");
o.println("<title>Hello World</title>");
o.println("</head>");
o.println("<body>");
o.println("<h1>Hello World!</h1>");
o.println("</body>");
o.println("</html>");
}
}
注意:对于上面的import部分以及异常处理,在eclipse或者其他IDE中可以直接通过建立一个servlet来导入
1.1.2 Servlet生命周期
实例化->init()->service()->destroy->销毁实例
对于多线程问题,可以采用synchronized来定义service(doGet)方法,从而使用队列处理
1.1.3 Servlet部署描述符
web.xml保存在/WEB-INF下,用于保存servlet的基本部署信息
servlet对应的class文件保存在/web-inf/classes中
<servlet>
<servlet-name>填写名字</servlet-name>
<servlet-class>对应的类名(要加入包名)</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>对应上面的name</servlet-name>
<url-pattern>映射到的网址</url-pattern>
</servlet-mapping>
1.1.4 ServletContext
定义了一系列方法用于Servlet通信,且每个JVM中的web-app中只有一个ServletContext
作用:
- 域对象
- 读取全局配置参数
- 搜索当前工程目录下的资源文件
/*ServletContext的应用*/
ServletContext context=this.getServletContext();
/*域对象*/
context.getAttribute(name);
context.setAttribute(name,value);
context.removeAttribute(name);
/*读取全局配置参数*/
context.getInitParameter(name);//根据指定的参数名获取参数值
context.getInitParameterNames();//获取所有参数名称列表
/*路径获取*/
context.getResourcePaths();
1.2 过滤器
Servlet过滤器可以检查和修改ServletRequest和ServletResponse对象
1.2.1 基本信息
作用:
- 查询请求并作出行为
- 阻塞请求响应对,使其不能进一步传递
- 修改请求头部和数据
- 修改响应头部和数据
- 与外界资源进行交互
适用场合:
- 认证过滤
- 登录和审核过滤
- 图像转换过滤
- 数据压缩过滤
- 加密过滤
- 资源访问触发事件过滤
1.2.2 编程步骤
编程步骤:
- 建立一个实现Filter接口的类
- 在doFilter方法中实现过滤行为
- 调用FilterChain对象中的doFilter方法
- 对相应的Servlet和JSP页面注册过滤器
- 禁用激活器servlet
/*设定过滤器处理所有的请求和响应的文本编码*/
package Filter;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import jakarta.servlet.*;
/**
* Servlet Filter implementation class MyFilter
*/
public class MyFilter extends HttpFilter {
private static final long serialVersionUID = 1L;
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("gb2312");
response.setContentType("text/html;utf-8");
chain.doFilter(request, response);//可以理解为过滤链,用于处理过滤
}
}
Servlet和Jsp的注册
<filter>
<filter-name>过滤器名字</filter-name>
<filter-class>对应的过滤器类</filter-class>
</filter>
<filter-mapping>
<filter-name>过滤器名字(对应)</filter-name>
<url-pattern>过滤路径</url-pattern>
<servlet-name>指定servlet过滤</servlet-name>
</filter-mapping>
1.3 会话
1.3.1 会话与会话管理
会话是指一个用户在客户端登录,为达到某个目的与服务器端多次交互最后退出应用系统的全过程(个人理解为每个人访问到浏览器关闭相关网页的过程)
会话机制:
- 一个web容器必须支持HTTP协议
- 会话HTTP为无状态协议
- 需要一种服务器端的机制维持会话状态信息
- 服务器使用散列表(Hash)来保存信息
会话过程:
- 客户端发送会话表示
- 会话识别过程
- 会话状态保存和获取
- 会话识别发送给客户端
1.3.2 会话追踪机制
- Cookies
- SSL Session
- URL重写
- 表单隐藏
- Cookies:引擎将用户ID保存在cookie中,发送该cookie到客户端,客户端将会在以后的请求中把这个cookie返回客户端(保存在windows的AppData文件夹下面,并且采用二进制形式无法被直接打开)
- SSL Sessions:采用HTTPS协议,非规范要求Servlet必须协议
- URL重写:将Session id写入URL中,URL会被解析为与某个Session相连
例如:
http://www.myservlet.com/index.html?jsessionid=1234
- 表单隐藏:利用HTML中的hidden属性,将表单字段传入服务器
<input type="hidden" name="user id" value=15>
1.3.3 会话编程
/*创建会话*/
HttpSession session=request.getSession(true);
//这里如果使用false就会调用一个已经有的会话
/*储存和访问会话属性*/
session.setAttribute(String s,Object o);
session.getAttribute(String s);
/*关闭会话*/
HttpSession.invalidate();
HttpSession.setInactiveInterval(int second); //设置超时时间,如果为负值用不超时
1.3.4 实例
/*购物车的例子*/
HttpSession session=request.getSession();
ShoppingCart cart;
synchronized(session){
cart = (ShoppingCart)session.getAttribute("shop");
if(cart==null){
cart=new ShoppingCart();
session.setAttribute("shop",cart);
}
}
1.4 事件监听
1.4.1 事件的分类和Listener接口
Application级别事件
- servlet
- Context
- Session级别事件(Http)
事件种类 | 事件描述 | 接口 |
---|---|---|
Context生命周期改变 | context建立与关闭 | ServletContextListener |
Context属性值改变 | 添加,删除,修改context属性 | ServletContextAttributeListener |
Session生命周期改变 | Session创建,销毁和超时 | HttpSessionListener |
Session属性值改变 | 添加,删除,修改Session属性值 | HttpSessionAttributeListener |
- ServletContext事件
事件类型 | 接口 | 方法 |
---|---|---|
创建Servlet上下文 | ServletContextListener | contextInitialized() |
关闭Servlet上下文 | ServletContextListener | contextDestroyed() |
添加特性 | ServletContextAttributeListener | attributeAdded() |
删除特性 | ServletContextAttributeListener | attributeRemoved() |
替换特性 | ServletContextAttributeListener | attributeReplaced() |
- Http会话事件
事件类型 | 接口 | 方法 |
---|---|---|
激活HTTP会话 | HttpSessionListener | sessionCreated() |
即将钝化HTTP会话 | HttpSessionListener | sessionDestroyed() |
添加特性 | HttpSessionAttributeListener | attributeAdded() |
删除特性 | HttpSessionAttributeListener | attributeRemoved() |
替换特性 | HttpSessionAttributeListener | attributeReplaced() |
1.4.2 事件监听器编程
- 实现上述的接口之一
- 创建不含任何参数的公共构造方法(默认构造器,如果重写了必须要写一个不带参的构造器)
- 编写对应的方法函数
例如:
package myApp;
import jakarta.Servlet.*;
public final class MySessionAttributeListenerClass implements HttpSessionAttributeListener{
public void attributeAdded(HttpSessionBindingEvent sbe){
/*当添加属性时调用该方法*/
}
public void attributeRemoved(HttpSessionBinding){
/*当删除属性时调用该方法*/
}
}
监听器部署:
<listener>
<listener-class>监听器类名</listener-class>
</listener>
1.4.3 例子
监听器实现对于网站在线人数的实时监控
package Listener;
import java.util.Enumeration;
import org.apache.jasper.compiler.NewlineReductionServletWriter;
import org.apache.tomcat.util.security.PrivilegedSetAccessControlContext;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextAttributeEvent;
import jakarta.servlet.ServletContextAttributeListener;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionContext;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
/**
* Application Lifecycle Listener implementation class OnLineCountListener
*
*/
public class OnLineCountListener implements HttpSessionListener, ServletContextAttributeListener, ServletContextListener {
private int count;
private ServletContext context=null;
private void log(String message) {
System.out.println("ContextListener:"+message);
}
public OnLineCountListener() {
count=0;
}
public void contextInitialized(ServletContextEvent event) {
this.context=event.getServletContext();
}
public void setContext(HttpSessionEvent se) {
se.getSession().getServletContext().setAttribute("onLine", new Integer(count));
}
public void sessionCreated(HttpSessionEvent se) {
count++;
setContext(se);
}
public void sessionDestroyed(HttpSessionEvent se) {
count--;
setContext(se);
}
public void attributeAdded(ServletContextAttributeEvent event) {
log("attributeAdded("+event.getName()+","+event.getValue()+")");
}
public void attributeRemoved(ServletContextAttributeEvent event) {
log("attributeRemoved("+event.getName()+","+event.getValue()+")");
}
public void attributeReplaced(ServletContextAttributeEvent event) {
log("attributeReplaced("+event.getName()+","+event.getValue()+")");
}
public void contextDestroyed(ServletContextEvent event) {
log("contextDestroyed()");
this.context=null;
}
}