Servlet编程

1. servlet概念及相关接口简介

java Servlet是运行在web服务器或应用服务器上的程序,他是作为来自web浏览器或其他HTTP客户端的请求和HTTP服务器山的数据库或应用程序之间的中间层

什么是Servlet

是一个java类,继承自HttpServlet类

这个类在服务器端运行,用以处理客户端的请求

主要作用

1.读取客户端(浏览器)发送来的显式数据和隐式的HTTP请求数据,包括html文件,cookies,HTTP请求等信息

2.处理数据被返回生成结果。

3.发送显式数据和隐式HTTP响应到客户端

2.开发一个Servlet流程

步骤:

1.编写java类,继承自HttpServlet类

2.重写doGet和doPost方法

3.Servlet程序交给tomcat服务器运行

3.1.servlet程序的class码拷贝到WEB-INF/calsses目录,如果是IDE,会自动拷贝

3.2.在web.xml文件中进行配置

3.3.配置的另一种方法是在servlet程序开头写上这样的语句,表示访问路径@WebServlet("/first")

先看servlet的程序

/**
* 运行在tomcat服务器端的servlet类
*/
@WebServlet(name = "FirstServlet")
public class FirstServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//向浏览器输出内容
response.getWriter().write("This is first servlet!");
//向控制台打印信息
System.out.println("helloWorld");
}
}

servlet程序写完之后还需要在WEB-INF目录下配置web.xml

配置如下:

    <!--配置一个servelt-->
<!--servlet的配置-->
<servlet>
<!--servlet的内部名称,名字可以自定义,但是最好有意义-->
<servlet-name>FirstServlet</servlet-name>
<!--servlet的类全名:包名+简单类名-->
<servlet-class>servers.FirstServlet</servlet-class>
</servlet> <!--servlet的映射配置-->
<servlet-mapping>
<!--servlet的内部名称,一定要和上面的内部名称保持一致-->
<servlet-name>FirstServlet</servlet-name>
<!--servlet的映射路径(访问servlet的名称)-->
<url-pattern>/first</url-pattern>
</servlet-mapping>

3.servlet路径映射

当我们访问 http://localhost:8080/sayhello/first路径时,是如何调用servlet呢?

xml路径开始之前:

tomcat服务器启动时,首先加载webapps中的每一个web应用的web.xml配置文件

http:// :http协议

localhost : 在本地的hosts文件中查找是否存在该域名对应的IP地址

8080 : 找到tomcat服务器

/sayhello : 在tomcat的webapps目录下找到sayhello目录

/first 资源名称

访问到/first时开始执行:

1.在sayhello的web.xml中查找是否有匹配的url-pattern的内容(/first)

2.如果找到匹配的url-pattern,则使用当前的servlet-name的名称到web.xml文件中查询是否有相同的servlet配置

3.如果找到,则取出对应的servlet配置信息中的servlet-calss内容

4.通过反射:

4.1.构造FirstServlet的对象

4.2.然后调用FirstServlet里面的方法

Servlet的映射路径

路径有两种精准匹配和模糊匹配两种方式

精确匹配:

/first 访问 http://localhost:8080/sayhello/first

模糊匹配:

  1. /* http://localhost:8080/sayhello/任意路径

    2./itcast/* http://localhost:8080/day10/sayhello/任意路径

    3.*.后缀名 例:×.do http://localhost:8080/sayhello/任意路径.do

注意:

1.url-pattern要么以 / 开头,要么以开头。 例如, itcast是非法路径。

2.不能同时使用两种模糊匹配,例如 /itcast/
.do是非法路径

3.当有输入的URL有多个servlet同时被匹配的情况下:

3.1 精确匹配优先。(长的最像优先被匹配)

3.2 以后缀名结尾的模糊url-pattern优先级最低!!!

4.缺省servlet

servlet的缺省路径(/)是在tomcat服务器内置的一个路径,该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的所用是用于解析web应用的静态资源文件

案例:URL输入http://localhost:8080/sayhello/index.html 如何读取文件????

1.首先到sayhello应用下的web.xml文件查找是否有匹配的url-pattern

2.如果没有匹配的url-pattern,则交给tomcat的内置DefaultServlet处理

3.DefaultServlet程序到sayhello应用的根目录下查找是否存在一个名称为index.html的静态文件

4.如果找到静态文件,则读取该文件内容,返回给浏览器

5.如果找不到该文件,则返回404错误页面

结论:先找动态资源,再找静态资源,不要轻易在web.xml使用/*,如果要使用,推荐加上后缀

5.servlet生命周期(重点)

5.1.引入

在之前接触的类中,可以使用new方法来创建一个对象,可以调用对象的方法,可以使对象等于null来消除对象。但是在servlet这个类中,我们只是重写了doGet等方法,并没有自己实现这个类的对象创建,初始化,调用,消除。

那么servlet这个类的生命周期是怎么样的呢?创建,初始化,调用,消除又是怎么实现的呢?

5.2.Servlet重要的四个生命周期方法

构造方法:创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象。只调用1次,证明servlet对象在tomcat是单实例的

init方法:创建完servlet对象的时候调用。只调用1次

service方法:每次发出请求时调用。请求几次调用几次

destory方法:销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象,只调用1次

代码示例:

/**
* 测试servlet的生命周期的四个重要方法
*/
@WebServlet(name = "LifeDemo")
public class LifeDemo extends HttpServlet {
//1.构造方法
public LifeDemo(){
System.out.println("1.LifeDemo被创建了");
} //2.inti方法
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("2.init方法被调用");
} //3.service方法
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("3.service方法被调用");
} //4.destory方法
@Override
public void destroy() {
System.out.println("4.servlet对象销毁");
}
}

5.3.伪代码演示servlet的生命周期

servlet是通过反射来调用的,这里使用伪代码模拟过程

tomcat内部代码运行

1.通过映射找到servlet-class的内容(字符串:servers.FirstServlet)

2.通过反射构造FirstServlet对象

2.1.得到字节码对象

Class clazz = class.forName("servers.FirstServlet");

2.2.调用无参的构造方法来构造对象

Object obj = clazz.newInstance(); ---1.servlet的构造方法被调用

3.创建ServletConfig对象,通过反射调用init方法

3.1.得到方法对象

Method m = clazz.getDeclareMethod("init",ServletConfig.class);

3.2.调用方法

m.invoke(obj,config); --2.servlet的init方法被调用

4.创建request,response对象,通过反射调用service方法

4.1 得到方法对象

Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

4.2 调用方法

m.invoke(obj,request,response); --3.servlet的service方法被调用

5.当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法

5.1 得到方法对象

Method m = clazz.getDeclareMethod("destroy",null);

5.2 调用方法

m.invoke(obj,null); --4.servlet的destroy方法被调用

5.4.用时序图来演示servlet的生命周期

5.5.Servlet的自动加载

默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。为了解决这个问题,我们可以设置在web应用第一次被访问的时候,就执行servlet的构造方法和init方法

改变servlet创建对象的时机: 提前到加载web应用的时候!!!

方法:

在servlet的配置信息中,加上一个即可!!

<servlet>
<servlet-name>LifeDemo</servlet-name>
<servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>
<!-- 让servlet对象自动加载 -->
<load-on-startup>1</load-on-startup>
</servlet>

注意: 整数值越大,创建优先级越低!!

6.有参的init方法和无参的init方法

有参的init方法是tomcat的生命周期方法。

无参的init方法使用提供给开发者重写该方法的地方

不要覆盖有参的方法,只能覆盖无参的方法

/**
* init有参和无参方法的区别
*/
@WebServlet(name = "InitDemo")
public class InitDemo extends HttpServlet {
/**
* 有参数的init方法
* 该方法是servlet的生命周期方法,一定会被tomcat服务器调用
* 这个init方法不能被覆盖
* @param config
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("有参的init方法");
} /**
* 无参数的init方法
* 该方法是servlet的编写初始化代码的方法
* 是sun公司设计出来专门给开发这进行覆盖的,然后在里面编写servlet的出事逻辑代码方法
* @throws ServletException
*/
@Override
public void init() throws ServletException {
System.out.println("无参的init方法");
}
}

7.Servlet线程安全

从上面的示例可以知道,Servlet是单实例,但是servlet又能被多客户端访问,所以又是一个多线程的。所以servlet是一个单实例多线程的

如果多线程同时访问了servlet对象的共享数据(成员变量)可能会引发线程安全问题

解决方法

1.把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)

2.建议在servlet类中尽量不要使用成员变量,如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围(建议哪里使用成员变量,就同步哪里!!),以避免因为同步导致并发效率降低

/**
* servlet的多线程并发问题
*/
@WebServlet("/thread")
public class ThreadDemo extends HttpServlet { int count=1; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8"); //多线程锁
synchronized (ThreadDemo.class) {//锁对象必须唯一,建议使用字节码
resp.getWriter().write("你现在是当前网站的第" + count + "个访客"); count++;
}
}
}

Servlet中的对象

HttpServletRequest 请求对象:获取请求信息

HttpServletResponse 响应对象: 设置响应对象

ServletConfig对象 servlet配置对象

ServletContext对象; servlet的上下文对象

8.servletConfig对象

8.1.作用

servletConfig对象:主要是用于加载servlet的初始化对象

8.2.对象创建和得到

创建时机:在创建完servlet对象之后,在调用init方法之前

得到对象:直接从有参数的init方法得到

8.3.servlet的初始化参数配置

ServletConfig的API:

java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值

java.util.Enumeration getInitParameterNames() 获取所有参数

ServletContext getServletContext() 得到servlet上下文对象

java.lang.String getServletName() 得到servlet的名称

配置文件:

    <servlet>
<servlet-name>ServletConfigDemo</servlet-name>
<servlet-class>servers.ServletConfigDemo</servlet-class>
<!-- 初始参数: 这些参数会在加载web应用的时候,封装到ServletConfig对象中 -->
<init-param>
<param-name>name</param-name>
<param-value>rocco</param-value>
</init-param>
</servlet>

ServletConfig的代码

/**
* 测试ServletConfig对象
*/
@WebServlet(name = "ServletConfigDemo")
public class ServletConfigDemo extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//读取servlet的初始参数
String name = this.getServletConfig().getInitParameter("name"); response.getWriter().write("hello");
System.out.println(name); }
}

9. ServletContext对象

9.1.引入

ServletContext对象,叫做Servlet的上下文对象。表示一个当前的web应用环境,一个web应用中只有一个ServletContext对象

9.2.对象创建和得到

创建时间:加载web应用时创建该对象

得到对象:从ServletConfig的getServletContext方法得到

9.3.ServletContext对象的核心API

得到ServletContext对象:

ServletContext context = this.getServletContext();

得到web应用路径

String getContextPath(); 得到当前web的应用路径

得到web应用的初始化参数(全局)

config参数是当前servlet的参数,只能由当前servlet对象获得

Context参数是全局参数,通过ServletContext对象,所有的都可以获得

全部参数的写法:

    <!--配置web应用参数-->
<context-param>
<param-name>AAA</param-name>
<param-value>AAA's value</param-value>
</context-param>
<context-param>
<param-name>BBB</param-name>
<param-value>BBB's value</param-value>
</context-param>
<context-param>
<param-name>CCC</param-name>
<param-value>CCC's value</param-value>
</context-param>

String getInitParameter(String name); 得到web应用指定的初始化参数

Enumeration geetInitParameterNames();得到web应用所有的初始化参数

域对象有关的方法

域对象:作用是用于保存数据,获取数据。可以在不同的动态资源之间共享数据

servlet是运行在服务器上的程序,如何在不同的servlet的程序之间传递参数的呢?常规做法是通过重定向后面附带参数来传递,例如:response.sendRedirect("/Servlet2?name=eric") 但是这样有一个问题,就是只能传递字符串的参数,且参数被暴露

最好的解决方案是使用域对象,域对象可以共享任何类型的数据

ServletContext其实就是一个域对象

ServletContext域对象:作用范围在整个web应用中有效!!!

域对象的一些操作

void setAttribute(java.lang.String name, java.lang.Object object) --保存数据

Object getAttribute(java.lang.String name) --获得数据

void removeAttribute(java.lang.String name) --删除数据

所有域对象:

HttpServletRequet域对象

ServletContext域对象

HttpSession 域对象

PageContext域对象

转发

转发和重定向的效果是一样的

RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(类似于重定向)

转发和重定向的区别

1.转发:

  • a.地址栏不会改变
  • b.转发只能转发到当前web应用内的资源
  • c.在转发过程中,可以把数据保存到request域对象中

2.重定向

  • a.地址栏会改变,变成重定向到的新地址
  • b.重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站
  • c.不能再重定向的过程中,把数据保存到request中

结论:如果要使用request域对象进行数据共享,只能使用转发技术

其他一些方法

通常在一个java路径中,我们用 . 表示项目文件所在的地址,但是在java web项目中,点 . 表示tomcat下bin里的startup.sh所在的目录。所以在java web中不能使用点 . 来查找文件

但是可以使用 “/” 来查找, / 表示WEB-INF所在的目录地址,通过这个找到资源文件

java.lang.String getRealPath(java.lang.String path) --得到web应用的资源文件

java.io.InputStream getResourceAsStream(java.lang.String path) 得到资源文件,但是返回的是一个输入流,不需要再转换

/**
* 测试ServletContext对象的核心API
*/
@WebServlet(name = "ServletContextDemo")
public class ServletContextDemo extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.得到ServletContext对象
//下面两种方法都可以,推荐使用第二种
// ServletContext context = this.getServletConfig().getServletContext();
ServletContext context = this.getServletContext();//推荐使用 //2.得到web应用路径
//web应用路径:部署到tomcat服务器上运行的web应用名称
String contextPath = context.getContextPath();
System.out.println(contextPath); //案例:请求重定向
response.sendRedirect(contextPath+"/index.html"); //3.得到web应用参数
String aaa = context.getInitParameter("AAA");//获取指定的一个
Enumeration<String> enums = context.getInitParameterNames();//得到所有 //4.域对象的一些操作
//保存到域对象中
context.setAttribute("name","tom");
//从域对象中获得数据
Object name = context.getAttribute("name");
//从域对象中删除数据 //5.转发,效果就是跳转页面
//不能转发到项目以外的路径
RequestDispatcher rd = context.getRequestDispatcher("/index.html");
rd.forward(request,response); /**
* 6.读取web应用下的资源文件
*/ //在java项目中,点 . 表示java项目所在的地址
//java web项目中,点 . 表示tomcat的bin目录,所以不能使用这种相对路径
// File file = new File("./src/db.properties");
// FileInputStream in = new FileInputStream(file); //正确获取
//方法1.getRealPath
// “/”表示WEB-INF所在目录地址
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
File file = new File(path);
FileInputStream in = new FileInputStream(file); //方法2: 得到资源文件,返回的是输入流
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Properties prop = new Properties();
//读取资源文件
prop.load(in); String user = prop.getProperty("user");
String password = prop.getProperty("password");
System.out.println(user+"="+password); }
}

Servlet编程的更多相关文章

  1. Servlet编程-步步为营

    [环境]eclipse j2ee;Tomcat 7.0; [模型1] package com.zhiqi; import ...; public class TestServlet extends H ...

  2. Java复习10.Servlet编程

    Java复习10. Servlet编程知识 20131008 前言: 之前在大三下的时候,学习了一个月的JSP和Servlet知识,但是没有什么项目经验,把JSP Web开发学习实录看了前面几张,后面 ...

  3. Servlet编程实例1

    编程目的:使用JSP+servlet,来实现一个登陆页面,登陆成功则提示成功,登陆失败则提示失败. 编程要求:登陆页面由login.jsp负责显示,登陆成功由success.jsp负责显示,登陆失败由 ...

  4. Servlet 编程 请求的转发

    在上篇的基础上,修改servlet *转发只能在同一应用内转发. 将forward 地址改为:youku.com  不能访问 重定向是可以访问外部应用的

  5. Servlet 编程 简单流程处理(重定向)

    流程(来自jiekexueyuan) servlet sucess.jsp error.asp同理 运行结果:

  6. Servlet编程实例2

    上次实验中利用HttpServletRespon.sendRedict()方法来实现页面的转跳,而这种重定向请求的方法无法传递缓存的内容. 所以为了做出改进,这次使用RequestDispatcher ...

  7. Servlet编程实例-servlet学习之旅(三)

    LoginServlet代码: public class LoginServlet extends HttpServlet{ @Override protected void service(Http ...

  8. servlet编程操作

    所谓servlet指:服务器处理来自Web浏览器或其他客户端的HTTP请求的服务器程序.客户端向服务器发送Http请求,经Tomcat封装处理转给Servlet容器,Servlet容器在把请求或回应交 ...

  9. Servlet编程实例 续4

    ---------------siwuxie095 JSP+Servlet+JDBC 继续完善登录实例,将校验逻辑改为:从数据库中获取用户信息进行校验 数据库准备 在 Navicat for MySQ ...

随机推荐

  1. highlight.js 代码高亮插件

    官网:https://highlightjs.org/ API:http://highlightjs.readthedocs.org/en/latest/api.html 1. 简单使用: <l ...

  2. 让我们山寨一张Windows Azure Global的壁纸

    用过国际版Azure的同学都见过一个显示了机器中主要信息的壁纸,而这个壁纸是通过Sysinternals的一款叫做bginfo来实现的,这款软件的好处是对于批量管理主(虚拟)机的管理员和使用方都很实用 ...

  3. 【Oracle 集群】Linux下Oracle RAC集群搭建之Oracle DataBase安装(八)

    Oracle 11G RAC数据库安装(八) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总 ...

  4. 理解CSS前景色和透明度

    前面的话 颜色的出现让网页不再只是黑白,运用好颜色设计,能让网页增色不少.一个网页给人们留下的第一印象实际上就是它的整体颜色.关于如何设置颜色,请移步CSS的6种颜色模式.实际上,颜色的应用主要分为前 ...

  5. ASP.NET MVC Controller的激活

    最近抽空看了一下ASP.NET MVC的部分源码,顺带写篇文章做个笔记以便日后查看. 在UrlRoutingModule模块中,将请求处理程序映射到了MvcHandler中,因此,说起Controll ...

  6. Sql常用语句(3)

    --显示sql server现有的所有数据库 exec sp_helpdb --查看数据表设置的约束 exec sp_helpconstraint SubjectType --update selec ...

  7. c#使用Split分割换行符 \r\n

    c# 使用Split分割 换行符,方法如下(其余方法有空再添加):   string str = "aa" + "\r\n" + "bb"; ...

  8. Ubuntu下的解压缩

    一. 命令: .tar 解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)———————————————.gz ...

  9. C#开发微信门户及应用(35)--微信支付之企业付款封装操作

    在前面几篇随笔,都是介绍微信支付及红包相关的内容,其实支付部分的内容还有很多,例如企业付款.公众号支付或刷卡支付.摇一摇红包.代金券等方面的内容,这些都是微信接口支持的内容,本篇继续微信支付这一主题, ...

  10. 自己动手写计算器v1.1

    这个改动主要是使用工厂模式替代了简单工厂模式,这样做的好处是如果以后我们要扩充其他运算时,就不用总是去修改工厂类, 这是可以采取工厂模式,主要是将原来简单工厂类的逻辑判断分离出来,将它作为一个借口,与 ...