[置顶] Web开发(一)---Servlet

Java Servlet是和平台无关的服务器端组件,功能是实现对客户端请求的响应。

Servlet组件运行在Servlet容器中,我们通常说的Servlet容器一般就指Tomcat服务器。

Servlet容器负责Servlet和客户的通信,以及调用Servlet的方法,Servlet和客户采用“请求/响应”的模式。

客户<---(请求/响应)--->Servlet容器<----(ServletRequest/ServletResponse)---->Servlet组件

Servlet可完成如下功能:

1.创建并返回基于客户请求的动态HTML页面

2.创建可嵌入到现有HTML页面中的部分HTML页面(Html片断)

3.与其他服务器资源进行通信,如数据库,基于Java的应用程序

Servlet其实就是一组Java程序,最顶层是接口Interface Servlet,Servlet组件实现该接口定义的方法,javax.servlet.Servlet接口

1、Servlet的创建与配置

在Eclipse中创建一个Dynamic Web Project,并且配置Tomcat服务器,选择next,最后可勾选web.xml的自动生成。

在src下创建package,并且创建HelloWorld类,实现Servlet接口,并且实现Servlet接口定义的方法,无参构造函数

public class HelloWorld implements Servlet{

	@Override
	public void destroy() {
		System.out.println("destroy");
	}

	@Override
	public ServletConfig getServletConfig() {
		System.out.println("getServletConfig");
		return null;
	}

	@Override
	public String getServletInfo() {
		System.out.println("getServletInfo");
		return null;
	}

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

	@Override
	public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
		System.out.println("service");
	}
	
	public HelloWorld() {
		System.out.println("HelloWorld constructor ...");
	}
}
配置web.xml文件,在WebContent/WEB-INF下,配置HelloWorld类的Servlet和映射

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletTest2</display-name>
  
  <servlet>
  	<servlet-name>HelloWorld</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>HelloWorld</servlet-name>
  	<url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

配置两个元素:servlet和servlet-mapping

url-pattern元素中的/hello,其中"/"代表web应用的根目录,也就是http://localhost:8080/项目名/

右键项目,运行在服务器上,在Eclipse或系统的浏览器上,输入网址http://localhost:8080/项目名/配置的url-pattern

在这里是http://localhost:8080/ServletTest/hello,Eclipes显示的结果为:

HelloWorld constructor ...

init

service

无限制刷新网页时,每次只显示service

关闭服务器,显示destroy

这说明了Servlet的生命周期。

web.xml文件中servlet的配置和映射,如果只配置servlet,不配置映射servlet-mapping,并且设置为Tomcat启动时加载,会显示:

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletTest2</display-name>
  
  <servlet>
  	<servlet-name>HelloWorld</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class>
  	<load-on-startup>1</load-on-startup>
  </servlet>

</web-app>

HelloWorld constructor ...

init

但不会显示service

注意:Servlet程序必须存储在"web应用程序目录\WEB-INF\classes\"目录中

2、Servlet的生命周期

使用Servlet时,我们不需要手动new类的实例,也不用手动调用方法,这一切都是Servlet容器帮我们完成的操作。

Servlet容器:运行Servlet、Jsp、Filter等的软件环境,可以来创建Servlet,并调用Servlet的相关生命周期方法。

由上节的HelloWorld可以看出,Servlet的生命周期:

1.构造方法:只被调用一次,只有在第一次请求Servlet时,才创建对应的Servlet实例,调用构造器。说明Servlet是单实例的!(单实例,就会存在线程安全问题,不推荐使用全局变量)

2.init方法:只被调用一次,在创建好实例后,立即被调用,用于初始化当前Servlet,init方法的形参有特殊的作用(ServletConfig类型的形参)。

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

4.destroy方法:只被调用一次,在当前servlet所在的web应用被卸载前调用,用于当前Servlet所占用的资源。

这些方法都是Servlet容器负责调用。

3、load-on-startup

在servlet元素配置中,加入load-on-startup的配置标签,是为了,不需要请求,在Tomcat服务器启动时就加载该Servlet。

数值为负数,在请求时加载;数值为0和整数,在服务器启动时加载,并init初始化,并且,数值越小,越早被加载创建

  <servlet>
  	<servlet-name>HelloWorld</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class>
  	<load-on-startup>0</load-on-startup>
  </servlet>
  
  
  <servlet>
  	<servlet-name>Second</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.SecondServlet</servlet-class>
  	<load-on-startup>3</load-on-startup>
  </servlet>
  
  
   <servlet>
  	<servlet-name>Third</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class>
  	<load-on-startup>5</load-on-startup>
  </servlet>
先创建加载HelloWorld,然后是Second,最后是Third

4、关于servlet-mapping

有关servlet-mapping的配置需注意两点

1.一个Servlet可以配置多个servlet-mapping,这样可以通过不同的url地址访问Servlet实例

2.url-pattern配置中使用通配符*只有两种合法的形式:

一种是 *.扩展名 的方法,例如 *.html,那么在访问web应用主目录 或者 aa.html 、.html时都可以请求到该Servlet

  <servlet>
  	<servlet-name>Third</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class>
  	<load-on-startup>5</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>Third</servlet-name>
  	<url-pattern>*.html</url-pattern>
  </servlet-mapping>
访问 :

web主目录:http://localhost:8080/ServletTest/ 

http://localhost:8080/ServletTest/.html

http://localhost:8080/ServletTest/aa.html都可以得到Servlet 的响应。

第二种是以正斜杠/开头,并以 /* 结尾

  <servlet>
  	<servlet-name>Third</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.ThirdServlet</servlet-class>
  	<load-on-startup>5</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>Third</servlet-name>
  	<url-pattern>/*</url-pattern>
  </servlet-mapping>
其他例如 /*.action 都不合法。

5、初始化参数及ServletConfig类

Servlet配置时,可以给需要的Servlet配置初始化参数,配置方法:在servlet标签下使用init-param标签

  <servlet>
  	<servlet-name>HelloWorld</servlet-name>
  	<servlet-class>com.cqupt.java.servlet.HelloWorld</servlet-class>
  	
  	<!-- init-param 标签必须放在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>1234</param-value>
    </init-param>
  	
  	<load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>HelloWorld</servlet-name>
  	<url-pattern>/hello</url-pattern>
  </servlet-mapping>
注意:init-param 标签必须放在load-on-startup标签之前 ,否则有错

那么如何在Servlet类中获取呢,关键在ServletConfig类,Servlet的init方法的形参就是ServletConfig类型

可以通过Servlet的init方法获取配置的初始化参数:

1.使用ServletConfig的getInitParameter(参数名)获取

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init get init-param");
		String user = config.getInitParameter("user");
		System.out.println("user:"+user);
		String password = config.getInitParameter("password");
		System.out.println("password:"+password);
	}

2.使用ServletConfig类的getInitParameterNames()获取所有参数名的Enumeration集合对象,再根据参数名获取参数值

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init get init-param");
		Enumeration<String> names = config.getInitParameterNames();
		while(names.hasMoreElements()){
			String name = names.nextElement();
			System.out.println(name+":"+config.getInitParameter(name));
		}
	}
也可以使用getServletName()获取Servlet的名字

System.out.println(config.getServletName());

还可以使用getServletContext获取ServletContext对象,经常使用。

ServletContext servletContext = config.getServletContext();

6、ServletContext

ServletContex同ServletConfig类一样,是Servlet中经常使用且很重要的类。

ServletContext对象代表当前Web应用:可以认为ServletContext是当前web应用的大管家,可以从中获取关于Web应用的各种信息。

1.设置当前Web应用的初始化参数,直接在web-app标签下配置context-param标签即可

  <!-- 配置当前web应用的初始化参数 -->
  <context-param>
  	<param-name>driver</param-name>
  	<param-value>com.mysql.jdbc.Driver</param-value>
  </context-param>
  <context-param>
  	<param-name>jdbcUrl</param-name>
  	<param-value>jdbc:mysql:///test</param-value>
  </context-param>

通过ServletContext配置的初始化参数可以被所有的Servlet获取,而Servlet配置的初始化参数只能被其自身获取。

通过getInitParameter(参数名)和getInitParameterNames()获取

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init ...");
		ServletContext servletContext = config.getServletContext();
		
		String driver = servletContext.getInitParameter("driver");
		System.out.println(driver);
		
		Enumeration<String> names = servletContext.getInitParameterNames();
		while(names.hasMoreElements()){
			String name = names.nextElement();
			String value = servletContext.getInitParameter(name);
			System.out.println(value);
		}
	}


2.获取当前Web应用的某一个文件在服务器上的绝对路径,而不是部署前的路径。

使用getRealPath(String path),path是根目录下的路径文件,以/开始

//note.txt在WebContent/下,获取的不是部署前的路径
		String realPath = servletContext.getRealPath("/note.txt");
		System.out.println(realPath);
		//D:\java\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\ServletTest\note.txt

3.获取当前web应用的名称

		String webName = servletContext.getContextPath();
		System.out.println(webName);
		//输出:/ServletTest
输出Web应用的名称,不是项目的名称,默认的Web名称是项目的名称,但是后期在配置服务器发布web应用时,经常会改变,通过这个方法可以动态获取到Web应用的名称。


4.获取文件输入流,getResourceAsStream(String path),其中path是当前Web应用的根目录开始的:"/"

		try{
			ClassLoader classLoader = getClass().getClassLoader();
			InputStream prop = classLoader.getResourceAsStream("jdbc.properties");
			System.out.println(prop);
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		try{
			//使用Servlet获取文件输入流,文件路径必须是从web应用开始
			//而在项目src下的所有文件都部署在web应用的/WEB-INF/classes/目录下
//			InputStream in = servletContext.getResourceAsStream("jdbc.properties");//null获取不到
			InputStream in = servletContext.getResourceAsStream("/WEB-INF/classes/jdbc.properties");
			System.out.println(in);
		}catch(Exception e) {
			e.printStackTrace();
		}

5.和Attribute相关的方法,后续。

7、HTTP协议

HTTP协议是超文本传输协议,是TCP/IP协议族的应用层协议,负责浏览器与服务器之间数据交换的过程,以及数据本身的格式。

HTTP协议是无状态的,每次网页的请求,都必须建立连接----发送请求-----返回数据-----断开连接,之所以服务器可以跟踪客户的网页访问,是Session起的作用(后续)

每次连接只处理一个请求和响应。

请求消息的结构:一个请求行,若干消息头,以及实体内容,消息头和实体内容之间要用空行隔开

响应消息的结构:一个状态行,若干消息头,以及实体内容,同样,消息头和实体内容之间要用空行隔开


请求方式有两种:GET请求和POST请求

GET请求,将参数附加在URL后,以键值对的方式,传送的数据是有限制的,一般在1kb以下

http://localhost:8080/ServletTest/loginServlet?user=bbb&password=123&submit=submit

POST请求,把参数插入在请求体里,传送的数据量比GET请求传送的多。

GET请求

1.在浏览器中输入URl地址或者单击网上的一个超链接时,浏览器发出的HTTP请求方法就是GET

2.如果网页的form表单指定了请求方法为GET,浏览器提交这个表单时,生成的HTTP请求消息的请求方式也是GET

3.使用GET请求为WEB服务器传参数格式:url?参数名1=参数1&参数名2&参数2

http://localhost:8080/ServletTest/loginServlet?user=bbb&password=123

4.使用GET请求传递的数据在1k以下,传递参数一般够用。

POST

1.网页表单form指定的请求方式为post,生成的HTTP请求使用POST方法

2.POST请求将form表单提交的数据作为HTTP消息的请求实体发送给WEB服务器,传递的数据比GET方法要大得多。

提交文件时,必须使用POST请求

你可能感兴趣的:([置顶] Web开发(一)---Servlet)