Java web开发——Servlet详细介绍

一、第一个Servlet程序

1、创建Servlet程序

在webapps目录下新建一个serfis的web应用,在serfis下新建一个WEB-INF\classes,在classes新建servlet(FirstServlet.java)

package com.shen;
import java.io.*;
import javax.servlet.*;


public class FirstServlet extends GenericServlet{
	
	public void service(ServletRequest req,ServletResponse res)
                      throws ServletException,java.io.IOException
        {
        	String data = "hello servlet!!";
        	OutputStream out = res.getOutputStream();
        	out.write(data.getBytes());	
        }
}

 

2、编译Servlet程序

     在cmd中进入classes目录,编译FirstServlet(cd/)

javac -d . FirstServlet.java
    set classpath=%classpath%;.............(.......为servlet的jar包存放的路径,因为默认的jar包只包含javaSE)
    将jar文件直接拖向cmd窗口

3、配置Servlet

     在serfis\web-inf目录,新建一个web.xml文件,对servlet进行配置

<web-app xmls="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-app_2_5.xsd"
    version="2.5">
    
    <servlet>
        <servlet-name>FirstServlet</servlet-name><!--自己取一个Servlet的名-->
        <servlet-class>com.shen.FirstServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>
        <url-pattern>/xxx</url-pattern><表示将该Servlet(FirstServlet)映射到xxx下(因为浏览器通过url访问),/表示当前web项目根目录>
    </servlet-mapping>
    
</web-app>

 

4、访问

     启动服务器,在ie输入http://localhost:8080/serfis/xxx

 

二、Servlet的生命周期

1、详情说明

1).构造器: 只被调用一次. 只有第一次请求 Servlet 时, 创建 Servlet 的实例. 调用构造器. (这说明 Serlvet 的单实例的!)

2). init 方法: 只被调用一次. 在创建好实例后立即被调用. 用于初始化当前 Servlet. 

3). service: 被多次调用. 每次请求都会调用 service 方法. 实际用于响应请求的. 

4). destroy: 只被调用一次. 在当前 Servlet 所在的 WEB 应用被卸载前调用. 用于释放当前 Servlet 所占用的资源. 

 

注意:在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。service对象在servlet生命周期中服务器只创建一次,并存在Tomcat服务器中,之后再调用该service取之前创建好的对象。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。 

 

2、运行原理

    

三、Servlet接口及派生类

1、Servlet接口

1.基本概念

     Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:

编写一个Java类,实现servlet接口。

把开发好的Java类部署到web服务器中。

2.程序举例

public class Servletan implements Servlet {
	@Override
	public void destroy() {//web应用被卸载时调用
		// TODO 自动生成的方法存根
		System.out.println("destroy");
	}

	@Override
	public ServletConfig getServletConfig() {封装了Servlet配置,并可以获取相关内容属性:servletcontextservletConfig...
		// TODO 自动生成的方法存根
		System.out.println("getServletConfig");
		return null;
	}
	@Override
	public String getServletInfo() {
		// TODO 自动生成的方法存根
		System.out.println("getServletInfo");
		return null;
	}
	@Override
	public void init(ServletConfig arg0) throws ServletException {//用于初始化,只调用一次
		// TODO 自动生成的方法存根
		System.out.println("init");
	}
	@Override
	public void service(ServletRequest arg0, ServletResponse arg1)//实际用于响应请求
			throws ServletException, IOException {
		// TODO 自动生成的方法存根
		System.out.println("service");
	}
	public void hello()
	{
		System.out.println("hello");
	}
}

2、HttpServlet实现类

1.基础概念

     HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。

     HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。

2.程序举例

public class HttpServletan extends HttpServlet {

	
	
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("hahhah!!");
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)//get请求的响应
			throws ServletException, IOException {
		
		response.getOutputStream().write("hahhaha".getBytes());

	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);//post请求交由get的请求响应
	}

}

 

3、GenericServlet实现类

四、servlet的配置

     在web.xml文件中配置,现有web程序为javaweb,有FirstServlet.java,

1、配置servlet实例

	<servlet>
		<!-- Servlet 注册的名字 -->
		<servlet-name>FirstServlet</servlet-name>
		<!-- Servlet 的全类名 -->
		<servlet-class>com.shen.FirstServlet</servlet-class>
	</servlet>

 

注意:可以通过load-on-startup参数来设置Serlvet 被创建的时机(即init()方法被调用的时间):若为负数, 则在第一次请求时被创建.若为 0 或正数, 则在当前 WEB 应用被

Serlvet 容器加载时创建实例, 且数组越小越早被创建.

<servlet>
		<!-- Servlet 注册的名字 -->
		<servlet-name>FirstServlet</servlet-name>
		<!-- Servlet 的全类名 -->
		<servlet-class>com.shen.FirstServlet</servlet-class>
		<!-- 可以指定 Servlet 被创建的时机 -->
		<load-on-startup>2</load-on-startup>
	</servlet>

2、将servlet实例映射到url

1.常规映射

<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/a.servlet</url-pattern><!---即通过访问localhost:8080/javaweb/a.servlet来访问该servlet-->
</servlet-mapping>

注意:

1). 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。一个Servlet仅仅是为一个页面进行服务,它本身并不代表一个页面。

如:

<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/a.servlet</url-pattern><!---即通过访问localhost:8080/javaweb/a.servlet来访问该servlet-->
</servlet-mapping>

<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/b.servlet</url-pattern><!---即通过访问localhost:8080/javaweb/b.servlet来访问该servlet-->
</servlet-mapping>

2.通配映射

     在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

//格式1
<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>*.do</url-pattern><!---即通过访问localhost:8080/javaweb/fsdf.do来访问该servlet-->
</servlet-mapping>

//格式2
<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/*</url-pattern><!---即通过访问localhost:8080/javaweb/fhgdf来访问该servlet-->
</servlet-mapping>

注意:

1). 以下的既带 / 又带扩展名的不合法. 

<servlet-mapping>
	<servlet-name>secondServlet</servlet-name>
	<url-pattern>/*.action</url-pattern>
</servlet-mapping>

2). 哪个长得像映射哪个,"/"的优先级高于"*"

如:Servlet1 映射到 /abc/* 

Servlet2 映射到 /* 

Servlet3 映射到 /abc 

Servlet4 映射到 *.do 

 

问题:

当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应?

Servlet引擎将调用Servlet1。

当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应?

Servlet引擎将调用Servlet3。

当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应?

Servlet引擎将调用Servlet1。

当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应?

Servlet引擎将调用Servlet2。

当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应?

Servlet引擎将调用Servlet2。

3.缺省映射

     如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求(如错误页面的处理)。 

<servlet-mapping>
	<servlet-name>FirstServlet</servlet-name>
	<url-pattern>/</url-pattern><!---即可以通过访问localhost:8080/javaweb/fhgdff'f来访问该servlet-->
</servlet-mapping>

注意:在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet(因为一个静态页面无需自己再配置一个servlet对其进行进行服务)。

五、servlet线程安全

  • 当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
  • 如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  • SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。
  • 实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。因此大多数web是线程不安全的

六、与servlet相关的对象

1、ServletConfig对象

1.介绍

     当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。

2.servlet中配置初始化参数

	<servlet>
		<servlet-name>helloServlet</servlet-name>
		<servlet-class>com.shen.HelloServlet</servlet-class>
		
		<!-- 配置 Serlvet 的初始化参数。 且节点必须在 load-on-startup 节点的前面 -->
		<init-param>
			<!-- 参数名 -->
			<param-name>user</param-name>
			<!-- 参数值 -->
			<param-value>root</param-value>
		</init-param>
		
		<init-param>
			<param-name>password</param-name>
			<param-value>1230</param-value>
		</init-param>
		
		<load-on-startup>-1</load-on-startup>
		
	</servlet>

 

3.获取初始化参数

     从init方法中取出初始化参数

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ConfigServletDemo1 extends HttpServlet {
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		    //获取指定的初始化参数的值
		    String value = config.getInitParameter("user");
            System.out.printfln(value)//打印出root

		    //获取所有的初始化参数
		    Enumeration e = config.getInitParameterNames();//Enumeration是一个迭代器
		    while(e.hasMoreElements()){
			     String name = (String) e.nextElement();
			     value = config.getInitParameter(name);
			     System.out.printfln((name + "=" + value + "<br/>").getBytes());//打印出user root password 1230         }
	}

}

     然而事实上大部分都在doXXX方法中取出初始化参数故

public class ConfigServletDemo1 extends HttpServlet {

	private ServletConfig config;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		//获取指定的初始化参数
		String value = config.getInitParameter("xxx");
		response.getOutputStream().write(value.getBytes());
		
		//获取所有的初始化参数
		Enumeration e = config.getInitParameterNames();//Enumeration是一个迭代器
		while(e.hasMoreElements()){
			String name = (String) e.nextElement();
			value = config.getInitParameter(name);
			response.getOutputStream().write((name + "=" + value + "<br/>").getBytes());
		}
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		this.config = config;
	}


}

     实际上在HttpServlet中重写了init方法(HttpServler继承于GenericServlet,GenericServlet重写了该方法),即同上,故可以在doXXX方法中直接调用ServletConfig

public class ConfigServletDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		ServletConfig config = this.getServletConfig();
		System.out.println(config.getInitParameter("user"));
		//获取指定的初始化参数
		String value = config.getInitParameter("user");
		response.getOutputStream().write(value.getBytes());
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

 

2、ServletContext对象

1.介绍

     WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。

2.servlet间数据共享

案例说明:有ServletDemo1,ServletDemo2,现ServletDemo1有数据data="shsj",将其共享给ServletDemo2。

//多个servlet通过servletContext实现数据共享
public class ServletDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String data = "shsj";
		
		ServletContext context = this.getServletConfig().getServletContext();//一般不用该方法
		context.setAttribute("datasss", data);  //map,将数据data放到关键字datasss中
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}
public class ServletDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		ServletContext context = this.getServletContext();
		String data = (String) context.getAttribute("datasss");//通过关键字获取数据
		System.out.println(data);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

3.WEB应用的初始化参数

1.全局初始化参数的配置

	<context-param>
		<param-name>url</param-name>
		<param-value>jdbc:mysql://localhost:3306/test</param-value>
	</context-param>

 

2.全局初始化参数的获取

//获取整个web站点的初始化参数
public class ServletContextDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		ServletContext context = this.getServletContext();
		String url = context.getInitParameter("url");
		System.out.println(url);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

4.实现Servlet的转发

案例说明:有ServletDemo1,ServletDemo2,现ServletDemo1有请求,将其转发给ServletDemo2处理。其中ServletDemo2的URL映射为/demo2

//用servletContext实现请求转发

public class ServletDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		
		ServletContext context = this.getServletContext();
		RequestDispatcher rd = context.getRequestDispatcher("/demo2");
		rd.forward(request, response);  //相当于调用ServletDemo2的doget(),故地址栏不变
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}
public class ServletDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		response.getOutputStream().write("servletDemo2来处理".getBytes());
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

分析:

如果ServletDemo1为:

//用servletContext实现请求转发
public class ServletDemo1 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		
		ServletContext context = this.getServletContext();
		RequestDispatcher rd = context.getRequestDispatcher("/demo2");
		rd.forward(request, response);  //相当于调用ServletDemo2的doget(),故地址栏不变
		System.out.println("我也执行了");
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

"我也执行了"将也会被打出,因为请求转发仅仅相当于调用ServletDemo2的doGet方法,如果ServletDemo1为:

//用servletContext实现请求转发
public class ServletDemo1 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		
		ServletContext context = this.getServletContext();
		RequestDispatcher rd = context.getRequestDispatcher("/demo2");
		rd.forward(request, response);  //相当于调用ServletDemo2的doget(),故地址栏不变
		response.getOutputStream().write("111".getBytes());
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

"111"不会被浏览器显示出来,因为response已经被发出一次,不会再发出,如果ServletDemo1为:

//用servletContext实现请求转发
//注意:
//1.转发之前的所有写入都无效
//2.转发之前,response不能提交,否则转发的时候服务器会抛:Cannot forward after response has been committed
public class ServletDemo1 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.getOutputStream().write("111".getBytes());//转发之前写入,值被覆盖
        
        /*
        OutputStream out=getOutputStream();
        response.out.write("111".getBytes());
        out.close //"111将会被写出但报错"
        */

		
		ServletContext context = this.getServletContext();
		RequestDispatcher rd = context.getRequestDispatcher("/demo2");
		rd.forward(request, response);  //相当于调用ServletDemo2的doget(),故地址栏不变
		
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

5.读取资源文件

   有资源文件db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root

1.资源文件在src目录下

//使用servletContext读取资源文件
public class ServleDemo extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test2();
	}
	
        //做web工程时,不建议采用传统方式读取文件数据
	public void test1() throws FileNotFoundException {
		FileInputStream in = new FileInputStream("db.properties");//在tomcat服务器中将db.properties文件拷贝到E:\Tomcat8.5\bin后
		System.out.println(in);
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	//读取web工程中资源文件的模板代码,一般就是这个
	private void test2() throws IOException {
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//源文件在src目录下
		Properties prop = new Properties();
		prop.load(in);
		
		String driver = prop.getProperty("driver");
		String url = prop.getProperty("url");
		String username = prop.getProperty("username");
		String password = prop.getProperty("password");
		
		System.out.println(driver);
	}

        //通过ServletContext获取路径后再采用传统方式
	private void test3() throws IOException {
		//获取web资源的绝对路径
		String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");//在src目录下
		FileInputStream in = new FileInputStream(path);
		
		Properties prop = new Properties();
		prop.load(in);
		
		String driver = prop.getProperty("driver");
		
		System.out.println(driver);
	}

2.资源文件在src目录下com.shen包下

	private void test4() throws IOException {
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/shen/db.properties");//源文件在src目录下
		Properties prop = new Properties();
		prop.load(in);
		
		String driver = prop.getProperty("driver");
		
		System.out.println(driver);
	}

3.资源文件在webroot目录下

	private void test5() throws IOException {
		//读取webroot目录下的资源
		InputStream in = this.getServletContext().getResourceAsStream("/db.properties");//在webroot目录下
		System.out.println(in);
	}

4.用类装载器读取

     如果一个资源文件在src下(包括包下),更常用类装载器来读取

//用类装载器读取资源文件
public class ServletContextDemo extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		test1();
	}
	

	private void test1() throws IOException {
		
		ClassLoader loader = ServletContextDemo.class.getClassLoader();//获取到装载当前类的类装载器
	
		InputStream in = loader.getResourceAsStream("db.properties");//用类装载器装载db.properties文件
		Properties prop = new Properties();
		prop.load(in);
		
		String driver = prop.getProperty("driver");
		
		System.out.println(driver);
	}
	//读取类路径下面、包下面的资源文件
	public void test2(){
		InputStream in = ServletContextDemo7.class.getClassLoader().getResourceAsStream("com/shen/db.properties");
		System.out.println(in);
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

注意:

1.通过类装载器读取资源文件的注意事项:不适合装载大文件,否则会导致jvm内存溢出

//通过类装载器读取资源文件的注意事项:不适合装载大文件,否则会导致jvm内存溢出
	public void test3(){
		InputStream in = ServletContextDemo7.class.getClassLoader().getResourceAsStream("PranavMistry_2009I_480.mp4");//如读取一个电影
		System.out.println(in);
	}


//文件太大,只能用servletContext
	public void test4() throws IOException{
		//读取PranavMistry_2009I_480.mp4,并拷贝到e:\根目录下
		
		//path=c:\asdf\adsd\add\PranavMistry_2009I_480.mp4
		//path=PranavMistry_2009I_480.mp4
		获取文件名
		String path = this.getServletContext().getRealPath("/WEB-INF/classes/PranavMistry_2009I_480.mp4");
		String filename = path.substring(path.lastIndexOf("\\")+1);//截取到文件名【lastIndexOf("\\")+1表示截取到字符串中最后一个'\'字符后的部分】
		
		//将该文件输入到内存(之前在web服务器)
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/PranavMistry_2009I_480.mp4");
		byte buffer[] = new byte[1024];
		int len = 0;
		//将该文件写入到硬盘
		FileOutputStream out = new FileOutputStream("e:\\" + filename);
		while((len=in.read(buffer))>0){
			out.write(buffer,0,len);
		}
		
		out.close();
		in.close();
	}

2.如果是一个普通的类,因为没有ServletContext对象故只能通过类的装载方法进行数据的读取,Dao.java,通过ServletDemo调用

public class ServletDemo extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		Dao dao = new Dao();
		dao.run();
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

dao.java

public class Dao {
	//读取资源文件,并更新资源文件
	public void run() throws IOException{
		
		URL url = this.getClass().getClassLoader().getResource("db.properties");
		String path = url.getPath();
		
	
		FileInputStream in = new FileInputStream(path);//读取数据
		FileOutputStream out = new FileOutputStream(path);//写入数据
		
		Properties prop = new Properties();
		prop.load(in);
		
		System.out.println(prop.size());
		
		prop.setProperty("name", "flx");
		prop.store(out, "");
		
		

		
	}
	
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ServletJavaEE 规范中的一部分,是处理 Web 请求的组件。Servlet 运行在服务器端,能够接收客户端发来的请求,并给客户端响应结果。下面我们来看看 Servlet 的基本概念和使用方法。 ## 一、Servlet 的基本概念 ### 1.1 Servlet 的生命周期 Servlet 的生命周期包含以下三个阶段: - 初始化阶段(init):当 Servlet 实例化后,Web 容器会调用其 init() 方法进行初始化操作。在此阶段,Servlet 可以执行一些初始化操作,例如读取配置信息、建立数据库连接等。 - 请求处理阶段(service):当客户端发来请求时,Web 容器会创建一个线程调用 Servlet 的 service() 方法处理请求。在此阶段,Servlet 可以获取请求参数、处理请求并生成响应数据。 - 销毁阶段(destroy):当 Web 应用停止或 Servlet 被卸载时,Web 容器会调用 Servlet 的 destroy() 方法进行清理工作。在此阶段,Servlet 可以释放资源、关闭数据库连接等。 ### 1.2 Servlet 的配置 在使用 Servlet 时,需要在 web.xml 文件中进行配置。以下是一个 Servlet 的基本配置: ```xml <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.example.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myservlet</url-pattern> </servlet-mapping> ``` 其中,servlet-name 表示 Servlet 的名称,servlet-class 表示 Servlet 的类名,url-pattern 表示请求的 URL 匹配规则。 ## 二、Servlet 的使用方法 ### 2.1 编写 Servlet 编写 Servlet 有两种方法:一种是继承 HttpServlet 类,另一种是实现 Servlet 接口。这里以继承 HttpServlet 类为例: ```java public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 GET 请求 PrintWriter out = resp.getWriter(); out.println("Hello, world!"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 POST 请求 PrintWriter out = resp.getWriter(); out.println("Hello, world!"); } } ``` 在 Servlet 中,doGet() 方法用于处理 GET 请求,doPost() 方法用于处理 POST 请求。通过调用 HttpServletResponse 对象的 getWriter() 方法可以向客户端返回响应数据。 ### 2.2 部署 Servlet 将编写好的 Servlet 部署到 Web 容器中,有两种方法:一种是将 Servlet 类打成 war 包放到 Web 容器的 webapps 目录下,另一种是通过 Eclipse 等开发工具将 Servlet 部署到 Web 容器中。部署完成后,可以通过访问 Servlet 的 URL 来测试 Servlet 是否正常工作。 ## 三、总结 本文介绍Servlet 的基本概念和使用方法。ServletJava Web 开发中非常重要的组件,掌握 Servlet 的使用方法对于 Java Web 开发人员来说是必不可少的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盡盡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值