servlet 执行顺序
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对象
- out对象是JspWriter类的实例,是向客户端输出内容常用的对象
5.page对象
- page对象就是指向当前JSP页面本身,有点象类中的this指针,它是
- java.lang.Object类的实例
- 序号方法说明
- classgetClass 返回此Object的类
- inthashCode() 返回此Object的hash码
- booleanequals(Objectobj) 判断此Object是否与指定的Object对象相等
- voidcopy(Objectobj) 把此Object拷贝到指定的Object对象中
- Objectclone() 克隆此Object对象
- StringtoString() 把此Object对象转换成String类的对象
- voidnotify() 唤醒一个等待的线程
- voidnotifyAll() 唤醒所有等待的线程
- voidwait(inttimeout) 使一个线程处于等待直到timeout结束或被唤醒
- voidwait() 使一个线程处于等待直到被唤醒
- voidenterMonitor() 对Object加锁
- 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 执行顺序的更多相关文章
- web.xml中多个Servlet执行顺序的问题!
1.两个servlet或者两个servlet-mapping,其中的servlet-name名称不能存在相同. 2.所有的servlet-mapping标签下,url-pattern中包含的文本不能相 ...
- Servlet 3.0 之@WebFilter怎么控制多个filter的执行顺序
之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行 <!-- ...
- web项目中的监听器,过滤器以及自定义servlet的执行顺序
可以看到web容器一启动就会实例化监听器的contextInitialized(ServletContextEvent event)方法,然后是过滤器的init()方法,最后在用户访问web应用的 时 ...
- filter、servlet、interceptor的执行顺序
1. Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能 ...
- 简单理解Struts2中拦截器与过滤器的区别及执行顺序
简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...
- netty4 Handler的执行顺序
转载:https://my.oschina.net/jamaly/blog/272385 Handler在netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通 ...
- filter的执行顺序
一直没有仔细去研究下filter ,最近系统的测试了下: 先看代码吧 FirstFilter.java ================== package com.test.filter; impo ...
- java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序
过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码 ...
- 04_过滤器Filter_03_多个Filter的执行顺序
[Filter链] *在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称为一个Filter链. *web服务器根据Filter在web.xml中的注册顺序,决定先调用哪个Fi ...
随机推荐
- 洛谷P1048 采药
题目OJ地址 https://www.luogu.org/problemnew/show/P1048 https://vijos.org/p/1104 题目描述辰辰是个天资聪颖的孩子,他的梦想是成为世 ...
- string与stringBuffer区别
string 的 “+” 操作就是根据 StringBuilder (或 StringBuffer )类及其 append 方法实现的. String 不可变其实就是说一个 String 对象创建之后 ...
- 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 ...
- docker 命令集
1.提交本地镜像到远程cd to dockerfile directorysudo docker build -t orange5 ./sudo docker psdocker tag 1adec2c ...
- 【原创 深度学习与TensorFlow 动手实践系列 - 3】第三课:卷积神经网络 - 基础篇
[原创 深度学习与TensorFlow 动手实践系列 - 3]第三课:卷积神经网络 - 基础篇 提纲: 1. 链式反向梯度传到 2. 卷积神经网络 - 卷积层 3. 卷积神经网络 - 功能层 4. 实 ...
- 关于网站中引用COM组件的部署问题
网站中引用了(PPT V14.0,即部署的服务器需要安装Office2010的)COM组件, 因此该功能对服务器有一定的环境要求: 1.安装Office2010,并激活. 2.配置: 1)开始-运行- ...
- 微信小程序,图片居中显示,适配不同机型
<view style='width:100%;height:100%;text-align:center;' class="picture-2"> <ima ...
- React+Webpack+Webstorm开发环境搭建
需要安装的软件 node.js npm包管理 Webstorm 由于6.3.0版本之后会自带npm的包管理所以不需要单独的安装npm nodejs(包含npm)安装在默认路径C:\Program Fi ...
- Tensorflow学习资源
https://tensorflow.google.cn/ 中文官网 https://www.w3cschool.cn/tensorflow_python/tensorflow_python-gnwm ...
- Android深入源代码分析理解Aidl总体调用流程(雷惊风)
2017年開始上班的第一天.老不想工作了,假期感觉还没開始就已经结束了,唉,时间就是这样,新的一年開始了,尽管非常不想干正事,没办法,必须干起来.由于后边的路还非常长,距离六十岁还非常远. 刚上班也没 ...