Servlet简介及其应用

Servlet

  • Servlet是一种动态网页技术
  • Servlet:server(服务器) applet (小程序),也叫服务器端小程序
  • Servlet能够接收浏览器的请求并且给浏览器以应答(响应)
  • Servlet解释分为广义和狭义的Servlet
    • 广义的servlet的指的是实现了javax.servet.Servlet接口的类
    • 狭义的servlet指的是javax.servlet.Servlet接口

Servlet的特征

  • Servlet是单例多线程的,只创建一个servlet对象,但是每次请求都会起一个线程并在自己线程栈内存中执行service方法
  • 一个 Servlet 实例只会执行一次无参构造器与 init()方法,并且是在第一次访问时执行
  • 用户每提交一次对当前 Servlet 的请求,就会执行一次 service()方法
  • 一个 Servlet 实例只会执行一次 destroy()方法,在应用停止时执行
  • 由于 Servlet 是单例多线程的,所以为了保证其线程安全性,一般情况下是不建议在 Servlet类中定义可修改的成员变量,因为每个线程均可修改这个成员变量,会出现线程安全问题
  • 默认情况下,Servlet 在 Web 容器启动时是不会被实例化的

Tomcat启动时实例化servlet实例
在tomcat启动时,默认不会创建servlet实例,如果想要让tomcat在启动时创建servlet实例的话,只需要在web.xml中添加load-on-startup标签即可

<servlet>
     <servlet-name>lifeServlet</servlet-name>
     <servlet-class>com.monkey1024.servlet.LifeServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
     <servlet-name>lifeServlet</servlet-name>
     <url-pattern>/life</url-pattern>
 </servlet-mapping>

添加load-on-startup的作用是,标记是否在 Tomcat启动时创建并初始化这个 Servlet实例。它的值必须是一个整数。

  • 当值大于等于 0 时,表示容器在启动时就加载并初始化这个 Servlet,数值越小,该 Servlet的优先级就越高,其被创建的也就越早;
  • 当值相同时,容器会自己选择创建顺序。

新建servlet有3种方式:

  • 1.实现Servlet接口
  • 2.继承GenericServlet
  • 3.继承HttpServlet

开发步骤:

  1. 新建 Dynamic Web Project
  2. 在项目中添加servlet-api.jar
    添加在WEB-INF/lib目录下
  3. 在src目录下,新建servlet,实现Servlet接口

servlet的访问方式
1.浏览器输入地址
2.超链接
3.form表单
4.window.location.href
浏览器方式:http://ip地址:端口号/项目名/访问路径

servlet生命周期(笔试题)

事物的生命周期指的是事物从创建到消亡的过程。
Servlet从创建到销毁的过程称为Servlet生命周期。

Servlet是单例多线程的
调用构造方法(实例化)---->init(初始化)----->service()–>doGet()|doPost()—>destory()
1次                                    1次                                     N次                                     1次

特别注意:如果servlet重写了service方法,那么service就专门负责处理请求(get|post)


HttpServletRequest

  • HttpServletRequest表示浏览器对服务器的请求
  • 关于浏览器对服务器的请求都被封装在HttpServletRequest对象

HttpServletResponse
表示服务器对浏览器的响应(应答)


RequestDispatcher

  • forward(ServletRequest request, ServletResponse response)
    在服务器上将一个请求从一个servlet转到另一个资源 (servlet, JSP文件, 或HTML文件)
  • include(ServletRequest request, ServletResponse response)
    包含一个资源 (servlet, JSP page, HTML文件)内容进一个响应消息
        //请求转发方式来实现(地址不变)
		request.getRequestDispatcher("a.html").forward(request,response );
		//请求包括方式实现同样的效果
		request.getRequestDispatcher("b.html").include(request, response);

转发和重定向区别?

  • forward 地址栏不变 一次请求 转发之间的servlet共享同一个request对象
  • sendRedirect 地址栏会改变 二次请求 servlet之间有各自独立的request对象

ServletConfig (了解)

  • ServletConfig表示的是Servlet的配置信息
  • ServletConfig对象和servlet配置信息()一一对应
  • 当服务器(tomcat)实例化Servlet时,会根据servlet配置信息创建ServletConfig对象

注意 配置初始化参数需要写在<servlet>…</servlet>中

  <servlet>
   ..........
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
    <init-param>
      <param-name>username</param-name>
      <param-value>password</param-value>
    </init-param>
    <init-param>
      <param-name>key</param-name>
      <param-value>value</param-value>
    </init-param>
  </servlet>

ServletConfig方法

  • getInitParameter(java.lang.String name)返回一个包含给定名字的初始化参数,若此参数不存在就返回一个空值。
  • getInitParameterNames()返回context的初始化参数的名字 ,用一个字符串对象枚举变量的形式。如果相应的context没有初始化参数,则就返回一个空的枚举变量
  • getServletName()返回该servlet实例的名称
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取ServletConfig对象
		ServletConfig config = this.getServletConfig();
		//获取在web.xml中的配置信息,如果不存在则返回一个空值
		String encoding = config.getInitParameter("encoding");
		//处理中文乱码问题
		response.setContentType("text/html;charset="+encoding);
		//打印中文字符
		response.getWriter().println("encoding:"+encoding+"<br/>");
		
		//获取所有的ServletConfig的初始化参数
		Enumeration<String> initParameterNames = config.getInitParameterNames();
		//遍历当前获取到的参数信息
		while (initParameterNames.hasMoreElements()) {
			String name = (String) initParameterNames.nextElement();
			//获取参数值
			String value = config.getInitParameter(name);
			response.getWriter().println(name+":"+value+"<br/>");
		}
		//返回该Servlet实例的名字
		String servletName = config.getServletName();
		response.getWriter().println(servletName);
	}

ServletContext

  • ServletContext表示一个WEB应用。
  • ServletContext是web.xml文件在内存中的表示。
  • ServletContext和web.xml一一对应

注意 在web.xml文件中配置全局初始化参数:

 <!-- context-param来配置项目的全局初始化参数信息 -->
  <context-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>  
  </context-param>
  <context-param>
      <param-name>username</param-name>
      <param-value>password</param-value>  
  </context-param>
  <context-param>
      <param-name>key</param-name>
      <param-value>value</param-value>  
  </context-param>

ServletContext有效范围
servletContext有效范围是从服务器启动到服务器停止之前,servletContext都有效

ServletContext方法

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   	//获取ServletContext对象
   	ServletContext context = this.getServletContext();
   	//读取全局全局初始化参数
   	String encoding = context.getInitParameter("encoding");
   	//处理响应乱码
   	response.setContentType("text/html;charset="+encoding);
   	//获取所有全局初始化参数信息
   	Enumeration<String> names = context.getInitParameterNames();
   	while (names.hasMoreElements()) {
   		String name = (String) names.nextElement();
   		//获取存储的value值
   		String value = context.getInitParameter(name);
   		response.getWriter().println(name+":"+value+"</br>");
   	}
   	//移除指定name键值对
   	context.removeAttribute("key");
   	String name1 = (String)context.getAttribute("key");
       response.getWriter().println(name1);
   } 

ServletContext可以向map集合一样,以键值对的形式存储数据


会话技术

目前我们是无法获取用户登录状态,servlet提供了2种获取(保存)用户登录状态的方式:

  • 1.cookie
  • 2.HttpSession

(1)cookie

  • Cookie是服务器向浏览器写入的一段字符串,这段字符串由键值对组成:”uname=zhang3”
  • Cookie是保存在浏览器上的

注意 存储和取需要在两个servlet里面

// 存储
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//创建cookie
		Cookie cookie1 = new Cookie("name1","admin1");
		Cookie cookie2 = new Cookie(URLEncoder.encode("用户1","utf-8"),"18");
		//设置cookie的有效期(单位/s)
		cookie1.setMaxAge(300);
		//将cookie对象添加到response
		response.addCookie(cookie1);
		response.addCookie(cookie2);
		//向浏览器打印
		response.getWriter().println(cookie1);
	}

获取cookie:

//取
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		//获取所有cookie
		Cookie[] cookies = request.getCookies();
		//遍历Cookie数组
		for (Cookie cookie : cookies) {
			response.getWriter().println(URLDecoder.decode(cookie.getName(),"utf-8")+":"+cookie.getValue()+"</br>");
		}	
	}

(2)HttpSession

  • HttpSession表示浏览器与服务器之间的会话(对象)。
  • HttpSession是保存在服务器。
  • Session默认是30分钟内有效,但是可以在web.xml文件中进行配置有效期:
<!-- 设置session有效时间,以分钟为单位 -->
//方式1:
  <session-config>
  <session-timeout>1</session-timeout>
  </session-config>
//方式2:
            //代码设置有效期,秒/单位
		    session.setMaxInactiveInterval(60);
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 //1.获取session
		   HttpSession session =   request.getSession();
		   //2.获取session的id
		    String id =  session.getId();
		    response.getWriter().print("session_id:"+id+"</br>");
		  //判断session是新还是旧
		    boolean b = session.isNew();
		    response.getWriter().print("boolean:"+b+"</br>");
		    //向seesion存储键值对
		    session.setAttribute("age", 18);
		    //取age
		    Integer value = (Integer)session.getAttribute("age");
		    response.getWriter().print("age:"+value+"</br>");
		    //移除age
		    session.removeAttribute("age");
		    //让当前的session失效;失效后再获取session将会出现异常
		    session.invalidate();
	}

Session获取原理
原理:首先服务器先检查浏览器中是否存在会话cookie,如果存在会话cookie,那么会根据会话cookie的值,查找相应的session,然后将查找到的session返回;如果不存在会话cookie,那么首先服务器会先创建session,然后再创建新会话cookie(JSESSION=SESSIONID),将会话cookie发送到浏览器,最后将新建的session返回。


过滤器
Filter译为过滤器。 由于Servlet规范是开放的,借助于公众与开源社区的力量,Servlet规范越来越科学,功能也越来越强大。2000年,Sun公司在Servlet2.3规范中添加了Filter功能,并在Servlet2.4中对Filter进行了细节上的补充。

运行原理:
当客户端向服务器端发送一个请求时,如果有对应的过滤器进行拦截,过滤器可以改变请求的内容、或者重新设置请求协议的相关信息等,然后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端做出响应时,过滤器同样可以进行拦截,将响应内容进行修改或者重新设置后,再响应给客户端浏览器。在上述过程中,客户端与服务器端并不需要知道过滤器的存在。
在一个Web应用程序中,可以部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程如下:
在这里插入图片描述实例:

  • Filter处理中文乱码问题
  • 自定义过滤器需要实现Filter接口

在java Resources下面建立一个util包,在建立一个Filter文件

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       //将ServletRequest强转成HttpServletRequest
   	HttpServletRequest request1=(HttpServletRequest)request;
   	//将ServletResponse强转成HttpServletResponse
   	HttpServletResponse response1=(HttpServletResponse)response;
   	
   	//处理请求乱码
   	request1.setCharacterEncoding("utf-8");
   	//处理相应乱码
   	response1.setContentType("text/html;charset=utf-8");
   	
   	//判断当前过滤器后面还有没有过滤器,如果有继续执行下一个过滤器
   	chain.doFilter(request, response);
   }

注意配置文件中

 <filter>
   <display-name>EncodingFilter</display-name>
   <filter-name>EncodingFilter</filter-name>
   <filter-class>util.EncodingFilter</filter-class>
 </filter>
 <filter-mapping>
   <filter-name>EncodingFilter</filter-name>
   <!-- /* 表示任何请求都交给过滤器处理 -->
   <url-pattern>/*</url-pattern>
 </filter-mapping>

监听器
web监听器是一种Servlet中的特殊的类,它们能帮助开发者监听web中的特定事件,比如ServletContext,HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控

Listener,java提供的监听器可以监听的对象包括:

  • 1.HttpServletRequest
  • 2.HttpSession
  • 3.ServletContext

在这里插入图片描述
统计网站访问量人数变化

在util包下创建监听文件

public void sessionCreated(HttpSessionEvent arg0)  { 
        //从ServletContext中获取当前在线人数
    	ServletContext context = arg0.getSession().getServletContext();
    	Integer count = (Integer)context.getAttribute("count");
    	if (count==null) {
			context.setAttribute("count", 1);
		}else{
			context.setAttribute("count", count+1);
		}
    	
    	//设置session的有效时间
    	arg0.getSession().setMaxInactiveInterval(30);
    	
    	System.out.println("有人上线");
    }

	/**
     * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
     */
    public void sessionDestroyed(HttpSessionEvent arg0)  { 
    	System.out.println("有人下线");
         ServletContext context = arg0.getSession().getServletContext();
         Integer count = (Integer)context.getAttribute("count");
         if (count==null || count<=0) {
			context.setAttribute("count", 1);
		}else{
			context.setAttribute("count", count-1);
		}
    }

网页显示人数:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   	Integer count = (Integer)request.getSession().getServletContext().getAttribute("count");
   	response.getWriter().println("当前在线人数:"+count);
   } 

监听器参考:https://www.cnblogs.com/w-wfy/p/6425357.html

发布了56 篇原创文章 · 获赞 6 · 访问量 7768

猜你喜欢

转载自blog.csdn.net/ly823260355/article/details/88927797