背景
在没有servlet之前,都是通过socket来处理http请求的;但是socket处理http请求的代码量比较多,并且需要自己来解析http协议;
实现一个web站点需要很多开发工作。特别是http协议解析的工作;
servlet的出现解决了这个问题,它是一个接口,专门用来处理http请求的;
1、servlet是什么
servlet是一个接口,定义了处理http请求的规范;
有两部分组成
- servlet服务器容器 tomcat、jetty、resin等;
- servlet接口实现类;业务开发,并将这些类丢到服务器容器中;发布成为一个站点
servlet服务器容器实现拦截初始化相关的servlet实例,并按照接口顺序依次调用方法;
┌───────────┐
│My Servlet │
├───────────┤
│Servlet API│
┌───────┐ HTTP ├───────────┤
│Browser│◀──────▶│Web Server │
└───────┘ └───────────┘
3、servlet生命周期
servlet生命周期:
1、初始化:调用init方法; 用户访问路径时,会创建servlet实例;只会创建一次
2、服务:调用service方法;用户访问路径时,会调用service方法;会多次调用。处理业务逻辑。
3、销毁:调用destroy方法;服务器关闭时,会调用destroy方法;只会销毁一次
备注 开发中一般使用HttpServlet,该类实现了service方法;主要用来判断请求类型,调用doGet或doPost方法;
4、servlet配置
4.1、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">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.jiang.servlet.user.LoginServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
<init-param>
<param-name>admin</param-name>
<param-value>123456</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>password</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
</web-app>
4.2、注解方式配置
注解属性值与xml配置文件属性值相对于
@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("Servlet is initialized.");
}
@Override
@SuppressWarnings("all")
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
String name = req.getParameter("name");
if (name == null) {
name = "world";
}
PrintWriter pw = resp.getWriter();
pw.write("<h1>Hello, " + name + "!</h1>");
pw.flush();
}
}
5、servlet的重定向与转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String redirectToUrl = "/hello"
// 发送重定向响应:
resp.sendRedirect(redirectToUrl);
// 代理转发:
req.getRequestDispatcher("/hello").forward(req, resp);
}
6、cookie与session
我们把这种基于唯一ID识别用户身份的机制称为Session。
每个用户第一次访问服务器后,会自动获得一个Session ID。
如果用户在一段时间内没有访问服务器,那么Session会自动失效,下次即使带着上次分配的Session ID访问,服务器也认为这是一个新用户,会分配新的Session ID。
在有效期内自动续期
- session的服务端sessionId存放在servlet服务器内存中;
- client端,如果是浏览器,则存放在cookie中;
备注
:
同一个域名的session默认id都是"JSESSIONID",同一个域名多个站点,需要在servlet服务器容器修改,避免冲突
7、servlet线程安全
servlet是单例的,且默认是线程不安全的;
如果需要线程安全,可以重写service
方法,在方法中加锁;
8、Filter
过滤器,顾名思义就是对事物进行过滤的。
在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等.
8.1、生命周期
初始化阶段:当服务器启动时,我们的服务器(Tomcat)就会读取配置文件,扫描注解,然后来创建我们的Filter。
拦截和过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循环。
销毁阶段:当服务器(Tomcat)关闭时,服务器创建的Filter也会随之销毁。
注解方式配置
import javax.servlet.annotation.WebFilter;
// FilterConfig是注解中的参数
@WebFilter(filterName = "LifeCycleFilter", urlPatterns = "/life")
public class LifeCycleFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
登录验证demo
@WebFilter(
value = "/*",
filterName = "LogFilter",
initParams = {@javax.servlet.annotation.WebInitParam(name="Site", value="JavaWeb"),@javax.servlet.annotation.WebInitParam(name="asd", value="dsa")},
servletNames = {"LogFilter"}
)
public class LogFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// 获取初始化参数
String site = config.getInitParameter("Site");
// 输出初始化参数
System.out.println("网站名称: " + site);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String urlPath = req.getRequestURI();
String url = req.getRequestURL().toString();
System.out.println("urlPath: " + urlPath);
// 把请求传回过滤链
if( urlPath.contains("/login") || urlPath.contains("/logout")){
chain.doFilter(request,response);
}
else{
HttpSession session =req.getSession(false);
if(session == null|| session.getAttribute("name") == null){
// 这是代理转发,不是重定向
// request.getRequestDispatcher("/login").forward(request,response);
res.sendRedirect( "/login");
}
else{
chain.doFilter(request,response);
}
}
}
public void destroy( ){
System.out.println("过滤器已销毁!");
}
}
9、Listener
9.1、Listener 基本信息
概念:监听器就是一个实现了特定接口的Java类。
分类:
- 一类监听器:监听域对象的创建、销毁
- 二类监听器:监听域对象中的属性变更(属性设置、属性替换、属性移除)
- 三类监听器:监听域对象中的java对象的绑定
9.2、一类监听器(对象监听器,创建销毁)
- ServletContextListener,监听ServletContext域对象的创建、销毁。服务器容器启动成功,销毁时触发
- HttpSessionListener 监听HttpSession域对象的创建、销毁。session创建触发sessionCreated方法,销毁时触发sessionDestroyed方法。代码中的创建session对象才会触发
- ServletRequestListener 监听ServletRequest域对象的创建、销毁。request创建触发requestInitialized方法,请求结束立即销毁时触发requestDestroyed;参数是事件对象,不能拦截
9.3、二类监听器(属性值监听器)
- ServletContextAttributeListener 监听ServletContext域对象中属性变更;早起站点中全局共享数据,发生变更时触发
- HttpSessionAttributeListener session级的属性值监听器
- ServletRequestAttributeListener 请求级的属性值监听器
9.4、三类监听器(对象绑定监听器)
- HttpSessionBindingListener 监听HttpSession域对象中java对象的绑定、解除绑 。 测试不生效
- ServletRequestBindingListener 监听ServletRequest域对象中java对象的绑定、解除绑定
10、servletContext
ServetContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
10.1、ServletContext对象方法
- getAttribute(String name) 获取属性值
- setAttribute(String name,Object obj) 设置属性值
- removeAttribute(String name) 移除属性
- getAttributeNames() 返回所有属性值;