public class TestServelt {

    public static void main(String[] args) {
ChildServlet childServlet = new ChildServlet();
childServlet.service();
} } class FatherServlet{ public void service(){
System.out.println("父类service");
doGet(); }
public void doGet(){
System.out.println("父类goGet");
} } class ChildServlet extends FatherServlet{ public void service(){
System.out.println("子类service");
super.service(); }
public void doGet(){
System.out.println("子类goGet");
} }

1、初始化阶段  调用init()方法

2、响应客户请求阶段。调用service()方法,由service()方法根据提交的方式选择执行doGet()或者doPost()方法

3、终止阶段  调用destroy()方法--关闭tomcat的时候

<servlet>
      <servlet-name>myServlet</servlet-name>
      <servlet-class>com.myServlet</servlet-class>
      <load-on-startup>1</load-on-startup>   启动tomcat的时候初始化当前servlet 调用init,数字越小越先加载
</servlet>

<context-param>
           <param-name>context/param</param-name>
           <param-value>avalible during application</param-value>
  </context-param>

参数通过getServletContext().getInitParameter("context/param")获取

<servlet>
    <servlet-name>MainServlet</servlet-name>
    <servlet-class>com.wes.controller.MainServlet</servlet-class>
    <init-param>
       <param-name>param1</param-name>
       <param-value>avalible in servlet init()</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
</servlet>

只能在servlet的init()方法中通过this.getInitParameter("param1")获取

Servlet不是线程安全的。

要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的。

当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个线程,之后找到该请求对应的Servlet对象并进行初始化,之后调用service()方法。要注意的是每一个Servlet对象再Tomcat容器中只有一个实例对象,即是单例模式。如果多个HTTP请求请求的是同一个Servlet,那么着两个HTTP请求对应的线程将并发调用Servlet的service()方法。

上图中的Thread1和Thread2调用了同一个Servlet1,所以此时如果Servlet1中定义了实例变量或静态变量,那么可能会发生线程安全问题(因为所有的线程都可能使用这些变量)。

比如下面的Servlet中的 name 和 i变量就会引发线程安全问题。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date; public class ThreadSafeServlet extends HttpServlet { public static String name = "Hello"; //静态变量,可能发生线程安全问题
int i; //实例变量,可能发生线程安全问题
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); @Override
public void init() throws ServletException {
super.init();
System.out.println("Servlet初始化");
} @Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
i++;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s:%s[%s]\n", Thread.currentThread().getName(), i, format.format(new Date()));
resp.getWriter().println("<html><body><h1>" + i + "</h1></body></html>");
}
} 在Tomcat中启动这个Servlet并在浏览器发起多个HTTP访问,最后会发现变量 i 是多线程共享的。 如果需要更加深入透彻地了解Tomcat接收HTTP的细节,以及与Servlet交互的细节,可以深入看看Tomcat的架构和源码。 jsp 9大内置对象 1.request对象
2.response对象
3.session对象
4.out对象
  1. out对象是JspWriter类的实例,是向客户端输出内容常用的对象

5.page对象

  1. page对象就是指向当前JSP页面本身,有点象类中的this指针,它是
  2. java.lang.Object类的实例
  3. 序号方法说明
  4. classgetClass 返回此Object的类
  5. inthashCode() 返回此Object的hash码
  6. booleanequals(Objectobj) 判断此Object是否与指定的Object对象相等
  7. voidcopy(Objectobj) 把此Object拷贝到指定的Object对象中
  8. Objectclone() 克隆此Object对象
  9. StringtoString() 把此Object对象转换成String类的对象
  10. voidnotify() 唤醒一个等待的线程
  11. voidnotifyAll() 唤醒所有等待的线程
  12. voidwait(inttimeout) 使一个线程处于等待直到timeout结束或被唤醒
  13. voidwait() 使一个线程处于等待直到被唤醒
  14. voidenterMonitor() 对Object加锁
  15. voidexitMonitor() 对Object开锁

6.application对象

application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器

的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前

后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何

地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和

关闭决定了application对象的生命。它是ServletContext类的实例。

7.exception对象

exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产

生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,

否则无法编译。他实际上是Java.lang.Throwable的对象

8.pageContext对象

pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是

说他可以访问到本页所在的SESSION,也可以取本页面所在的application的

某一属性值,他相当于页面中所有功能的集大成者,它的本类名也叫

pageContext。

9.config对象

config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)

HttpSession

是基于Cookie  实现的

HttpSession的创建时间

jsp中   显示调用时会创建session

servlet  中调用  request.getSession时会创建session


自定义标签

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1"> <description>testjsp 1.1 core library</description>
<display-name>testjsp core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>testjsp</short-name>
<uri>http://tj.com/testjsp</uri> <tag>
<!-- 描述 HelloSimpleTag的名称-->
<name>hello</name>
<tag-class>com.tag.TestJspFragment</tag-class>
<body-content>scriptless</body-content> <attribute>
        <name>value</name>
        <!-- 是否必须 -->
        <required>true</required>
        <!-- 是否支持EL表达式 -->
        <rtexprvalue>true</rtexprvalue>
     </attribute> <!-- 标签体 -->
<!-- 没有标签体 -->
<!-- <body-content>empty</body-content> -->
<!-- 不经过处理直接把内容交给标签处理器类 -->
<!-- <body-content>tagdependent</body-content> --> <!-- 可以有EL${} 不可以有<%=%> 大部分情况下取值为scriptless-->
<body-content>scriptless</body-content> </tag>
</taglib> public class TestJspFragment extends SimpleTagSupport{
    
    
    @Override
    public void doTag() throws JspException, IOException {
        //当定义标签体的时候会调用setJspBody(JspFragment arg0) {
        //把JspFragment传递过来
    
        JspFragment fragment = getJspBody();
        
        StringWriter sw = new StringWriter();
        //若为NULL输出到页面 等同于fragment.invoke(getJspContext().getOut());
        fragment.invoke(sw);
        //把内容写到sw中
        
        String content = sw.toString().toUpperCase();
        //把内容转换成大写写入到页面
        getJspContext().getOut().print(content);
        
        
    } } //InputStream inputStream = pageContext.getServletContext().getResourceAsStream("src");//根路径 //如果有标签体就会调用此方法,把JspFragment传过来
    public void setJspBody(JspFragment arg0) {
        System.out.println("setJspBody");
    } public void setParent(JspTag arg0) {
        //父标签获取不到子标签,子标签可以获取到父标签的引用
        System.out.println("setParent");
        
        //arg0指的就是父标签的引用,需要强转
        
    }
/*Cookie cookie = new Cookie("name", "aaaa");
//cookie 的作用范围默认为当前文件路径的子目录
cookie.setPath("/");//站点的根目录
cookie.setMaxAge(30);//最大秒数,存在磁盘对应当前浏览器,同一个站点最多存20个cookie,每个cookie最大4k //客户端第一请求时 服务端给客户端返回一个cookie 在请求头中set-cookie
//第二次客户端访问服务端会带着cookie
response.addCookie(cookie);*/ //response.encodeURL("session/a.jsp"); response.encodeUrl("session/a.jsp");//实现URL的重写,在后边加上;jeesessionid=331232131321 //服务端获取客户端cookie /*Cookie []cookies = request.getCookies(); if(cookies!=null){ for (Cookie coo : cookies) {
System.out.println(coo.getName()+":"+coo.getValue());
} }*/
 
//http://localhost:8080/spring1/IndexServlet
String method = request.getServletPath();//IndexServlet try {
Method me = getClass().getDeclaredMethod("add", request.getClass(),response.getClass());
me.invoke(this, request,response);
//cs.getDeclaredMethod("add", null).invoke(this, null);
} catch (Exception e) {
e.printStackTrace();
}

自定义标签函数

之前例子已经写好了,由于时间关系一直没有发布,这次带来的是关于taglib中的<tag>的基本功能已经介绍完毕了,在taglib中我们发现有一个标签叫做<function>,这次简单介绍<function>标签的基本用法,<function>标签可以做什么呢?它可以让我们在jsp用直接调用某个方法,根据自定义的方法返回指定的值,兼容jstl标签,省去了在jsp中直接使用<%!%>来定义方法体再调用的繁琐.如果你用过el语言的话估计会很快上手,其实<function>标签就是一个拥有方法体的el语言.注意:function所定义的方法必须需要是静态的,如果不是静态的话jstl是不能识别所定义的方法.

Java代码如下:

package org.lxh.taglib;

import java.util.List;

public class FunctionTag {

	public static String hello(String name) {

		return name;
} public static Integer bbq(List list) { return list.size();
}
}

方法必须静态,可以定义有返回值或者void类型的方法.

tld:

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>my</short-name>
<uri>http://lauedward.spaces.live.com</uri>
<function>
<!--EL页面调用名字-->
<name>hello</name>
<!--指定标签的处理类,指定了标签由哪个Java类来处理。-->
<function-class>org.lxh.taglib.FunctionTag</function-class>
<!--指定EL页面调用名字中实际调用的方法.指定处理类的实际方法.参数和回调函数要写完整路径-->
<function-signature>java.lang.String hello(java.lang.String)</function-signature> </function> <function>
<name>bbq</name>
<function-class>org.lxh.taglib.FunctionTag</function-class>
<function-signature>java.lang.Integer bbq(java.util.List)</function-signature>
</function>
</taglib>

注意:在<function-signature>需要写完整的类名,假如是String类型的话就必须写java.lang.String这样字,不支持泛型的定义如java.util.List<java.lang.String>eclipse会把<>当作xml的格式来判断的,所以就省略该泛型的定义.

jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="my" uri="/WEB-INF/tld/testFunction.tld"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@page import="java.util.*"%><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
    List<String> list = new ArrayList<String>();
    list.add("aa");
    list.add("bb");
    list.add("cc");
    request.setAttribute("list", "helloword");
    request.setAttribute("name", list);
    Map map = new HashMap();
    map.put("1","a");
    map.put("2","b");
    map.put("3","c");
    map.put("4","d");
%>

<br>
${my:hello(list)}
<br>
${my:bbq(name)}
<br>

</body>
</html>

注意:调用方法的时候必须类型要传入相同类型的值,否则的话会报错,不过对于方法体是String的话,是可以传入list,set,map那些,因为传入后会直接调用list的.toString()方法直接当字符串输出.


HttpSessionListener

HttpSessionAttributeListener

ServletContextListener

web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ,而同个类型之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。
												

servlet 执行顺序的更多相关文章

  1. web.xml中多个Servlet执行顺序的问题!

    1.两个servlet或者两个servlet-mapping,其中的servlet-name名称不能存在相同. 2.所有的servlet-mapping标签下,url-pattern中包含的文本不能相 ...

  2. Servlet 3.0 之@WebFilter怎么控制多个filter的执行顺序

    之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行   <!-- ...

  3. web项目中的监听器,过滤器以及自定义servlet的执行顺序

    可以看到web容器一启动就会实例化监听器的contextInitialized(ServletContextEvent event)方法,然后是过滤器的init()方法,最后在用户访问web应用的 时 ...

  4. filter、servlet、interceptor的执行顺序

    1. Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能 ...

  5. 简单理解Struts2中拦截器与过滤器的区别及执行顺序

    简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...

  6. netty4 Handler的执行顺序

    转载:https://my.oschina.net/jamaly/blog/272385 Handler在netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通 ...

  7. filter的执行顺序

    一直没有仔细去研究下filter ,最近系统的测试了下: 先看代码吧 FirstFilter.java ================== package com.test.filter; impo ...

  8. java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序

    过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码 ...

  9. 04_过滤器Filter_03_多个Filter的执行顺序

    [Filter链] *在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称为一个Filter链. *web服务器根据Filter在web.xml中的注册顺序,决定先调用哪个Fi ...

随机推荐

  1. 洛谷P1048 采药

    题目OJ地址 https://www.luogu.org/problemnew/show/P1048 https://vijos.org/p/1104 题目描述辰辰是个天资聪颖的孩子,他的梦想是成为世 ...

  2. string与stringBuffer区别

    string 的 “+” 操作就是根据 StringBuilder (或 StringBuffer )类及其 append 方法实现的. String 不可变其实就是说一个 String 对象创建之后 ...

  3. How to trigger a Kubernetes cronjob manually-手动触发一个cronjob

    What should you do when you’ve developed and installed a cron job for your Kubernetes application, a ...

  4. docker 命令集

    1.提交本地镜像到远程cd to dockerfile directorysudo docker build -t orange5 ./sudo docker psdocker tag 1adec2c ...

  5. 【原创 深度学习与TensorFlow 动手实践系列 - 3】第三课:卷积神经网络 - 基础篇

    [原创 深度学习与TensorFlow 动手实践系列 - 3]第三课:卷积神经网络 - 基础篇 提纲: 1. 链式反向梯度传到 2. 卷积神经网络 - 卷积层 3. 卷积神经网络 - 功能层 4. 实 ...

  6. 关于网站中引用COM组件的部署问题

    网站中引用了(PPT V14.0,即部署的服务器需要安装Office2010的)COM组件, 因此该功能对服务器有一定的环境要求: 1.安装Office2010,并激活. 2.配置: 1)开始-运行- ...

  7. 微信小程序,图片居中显示,适配不同机型

    <view style='width:100%;height:100%;text-align:center;' class="picture-2">   <ima ...

  8. React+Webpack+Webstorm开发环境搭建

    需要安装的软件 node.js npm包管理 Webstorm 由于6.3.0版本之后会自带npm的包管理所以不需要单独的安装npm nodejs(包含npm)安装在默认路径C:\Program Fi ...

  9. Tensorflow学习资源

    https://tensorflow.google.cn/ 中文官网 https://www.w3cschool.cn/tensorflow_python/tensorflow_python-gnwm ...

  10. Android深入源代码分析理解Aidl总体调用流程(雷惊风)

    2017年開始上班的第一天.老不想工作了,假期感觉还没開始就已经结束了,唉,时间就是这样,新的一年開始了,尽管非常不想干正事,没办法,必须干起来.由于后边的路还非常长,距离六十岁还非常远. 刚上班也没 ...