JavaEE之WEB项目开发(使用Servlet+Tomcat)

一、WEB项目的演变

1.发展规律

  • 由单机向网络发展
  • 由CS向BS发展

2.CS和BS的区别

1)CS

  • Client Server
  • 客服端服务器程序
  • 客户端需要单独开发,用户需要单独下载并安装

2)BS

  • Browser Server
  • 浏览器服务器程序
  • 客户端不用单独开发,用户不用单独安装

二、Servlet介绍(*)

1.服务器如何保存并返回一个网页?

1)静态网页

  • 无论谁看其内容都一样
  • 百科、新闻
  • 服务器直接存HTML,直接返回HTML即可

2)动态网页

  • 不同人看到的内容有差异
  • 淘宝、微博
  • 服务器保存一个组件,动态给每个用户拼一个网页
  • 在Java语言中这个组件就是Servlet

组件:满足规范的对象

2.Servlet的特点

  • 是服务器端的组件
  • 满足sun的规范
  • 可以动态拼资源(HTML/IMG等)

术语:处理HTTP协议

3.什么是Servlet?

  • 是sun推出的用于在服务器端处理HTTP协议的组件

三、服务器

1.名称

  • Java服务器
  • WEB服务器
  • Java WEB服务器
  • Servlet容器

2.本质

  • 是一个软件
  • 它和浏览器是平级的关系

3.举例

  • Tomcat(Apache)
  • JBoss
  • WebLogic
  • WebSphere

四、Tomcat的使用方式

1.单独使用(项目上线时)

1)配置好JAVA_HOME

2)下载及安装

  • 去Apache官网
  • 安装配置自行百度

3)启动tomcat

  • Linux:打开/tomcat/bin,在终端输入chmod +x *sh
  • Linux:打开/tomcat/bin,在终端输入./startup.sh
  • windows:打开/tomcat/bin,双击startup.bat

4)访问tomcat

  • 在浏览器上输入http://localhost:8080
  • 回车后看到一只猫咪

5)关闭tomcat

  • Linux:打开/tomcat/bin,在终端输入./shutdown.sh
  • windows:打开/tomcat/bin,双击shutdown.bat

2.通过Eclipse调用(开发时)

  • 点击window -> preferences -> server -> Runtime Environments -> add …
  • 在Eclipse中将自动生成Servers项目

补充

1.tomcat常见使用问题

1)问题描述

  • 在启tomcat时看到如下错误
  • adress already in use,JVM_BIND:8080

2)产生的原因

  • 重复启动tomcat造成8080端口冲突
  • 可能其他软件占用了8080端口

3)解决方案

  • 启动原因:打开/tomcat/bin目录,通过命令强制关闭它
  • 其它软件:打开server.xml,在65行修改tomcat端口

建议修改为8088/8089,修改后重启tomcat才生效

五、Servlet开发步骤

1.创建WEB项目

  • 必须具备标准的WEB目录
  • /webapp/WEB-INF/web.xml

2.导入jar包

1)使用maven

  • 使用maven搜索javaee
  • 在结果中选择javaee-api

2)使用tomcat自带的包(一般使用这个)

  • 选择项目右键点击properties
  • 弹出框里在左侧选择Targeted Runtimes
  • 在右侧勾选Apache Tomcat
  • Apply

3.开发Servlet

1)编写Servlet

  • 创建package
  • 创建一个类,名为XxxServlet
  • 继承HttpServlet,从而间接的实现了Servlet接口
  • 重写父类的service()

2)配置Servlet

  • 先声明类,并给它去别名
  • 在通过别名引用此类,给他取一个访问路径

4.部署(拷贝)

  • 在Servers视图下,选择tomcat7
  • 右键点击Add and Remove
  • 在弹出框内将左边的待部署项目移动到右侧
  • 启动tomcat即可

5.访问

  • 格式: http://ip:port/项目名/网名
  • 例子: http://localhost:8080/servlet1/ts

六、案例(浏览器显示系统时间)

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第1张图片

目录结构

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第2张图片

TimeServlet代码

package web;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

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

public class TimeServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) 
						  throws ServletException, IOException {
		//1.使用request接收请求数据
		//1)请求行(3)
		System.out.println("协议类型:"+req.getProtocol());
		System.out.println("访问路径:"+req.getServletPath());
		System.out.println("请求方式:"+req.getMethod());
		//2)消息头(键值对)
		//该数据是按照键值对的方式存储的
		//Enumeration是一个古老的迭代器,
		//其用法和Iterator相似.
		Enumeration<String> e = req.getHeaderNames();
		while(e.hasMoreElements()) {
			String key = e.nextElement();
			String value = req.getHeader(key);
			System.out.println(key + ":" + value);
		}
		//3)实体内容
		//本案例没有传递具体的业务数据
		//2.使用response发送响应数据
		//1)状态行
		//该数据由服务器自动填充
		//2)消息头
		//消息头中的大部分数据由服务器填充,但返回的内容格式需要程序员指定
		
			
		//告诉浏览器向它发送的是什么类型的内容
		res.setContentType("text/html");
		//获取输出流,该流指向的目标是浏览器
		PrintWriter pw = res.getWriter();
		//获取服务器的时间
		//将时间拼到一个网页里给浏览器返回
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		String now = sdf.format(date);
		//3)实体内容
		//我们输出的网页就是实体内容
		//此处偷懒,拼一个简化版的网页
		pw.println("

" + now + "

"
); //关闭输出流 pw.close(); } }

web.xml配置文件代码



<servlet>
	<servlet-name>timeservlet-name>
	<servlet-class>web.TimeServletservlet-class>
servlet>

<servlet-mapping>
	<servlet-name>timeservlet-name>
	
	<url-pattern>/tsurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第3张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第4张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第5张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第6张图片

七、HTTP协议

1.什么是HTTP

  • 就是一个规范(w3c)
  • 规定了浏览器和服务器如何通信以及通信的数据格式

2.如何通信

  • 浏览器和服务器建立连接
  • 浏览器向服务器发送请求
  • 浏览器接受响应
  • 断开连接

一次请求一次链接,降低服务器的压力

3.数据格式

1)请求数据

  • 请求行:请求的基本信息
  • 消息头:请求数据的描述
  • 实体内容:具体的业务数据

2)响应数据

  • 状态行:响应的基本信息
  • 消息头:响应数据的描述
  • 实体内容:具体的返回数据

代码实现,见上一个案例的代码注释

4.HTTP对开发者的要求

1)不用开发者处理的地方

  • 浏览器自动打包发送请求数据
  • 服务器自动打包发送响应数据

2)需要开发者处理的地方

  • 提供具体的请求中的业务数据
  • 提供具体的响应中的返回数据
  • 通过request处理请求数据,通过response处理响应数据

要求开发者会使用request和response就行了

八、注册案例

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第7张图片

1. 以下涉及的乱码问题的解决方法(三种)

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第8张图片

2. RegServlet.java代码

package web;
import java.io.IOException;
import java.io.PrintWriter;

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

public class RegServlet extends HttpServlet {

	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		//采用方案三解决POST请求乱码问题(在接受数据之前)
		req.setCharacterEncoding("utf-8");
		//处理请求的一般流程
		//1.接收参数
		String name = req.getParameter("userName");
		String pwd = req.getParameter("pwd");
		String sex = req.getParameter("sex");
		String[] interests = req.getParameterValues("interest");
		
		//采用方案一解决乱码问题
		//byte[] bs = name.getBytes("iso8859-1");
		//name = new String(bs,"utf-8");
		
		//2.处理业务
		//常规的注册业务应该保存这些数据,此处就输出下
		System.out.println(name);
		System.out.println(pwd);
		System.out.println(sex);
		if(interests != null) {
			for(String interest : interests) {
				System.out.println(interest);
			}
		}
		//3.发送响应
		res.setContentType("text/html;charset=utf-8");
		PrintWriter w = res.getWriter();
		w.println("

ok,"+name+"

"
); w.close(); } }

3. register.html代码


<html>
<head>
<meta charset="UTF-8">
<title>注册title>
head>
<body>
	
	<form action="reg" method="post">
		<p>
			账号:<input type="text" name="userName"/>
		p>
		<p>
			密码:<input type="password" name="pwd"/>
		p>
		<p>
			性别:
			<input type="radio" name="sex" value="M"/><input type="radio" name="sex" value="F"/>p>
		<p>
			兴趣:
			<input type="checkbox" name="interest" value="food"/>美食
			<input type="checkbox" name="interest" value="game"/>竞技
			<input type="checkbox" name="interest" value="friend"/>社交
		p>
		<p>
			<input type="submit" value="注册"/>
		p>
	form>
body>
html>

4. 配置文件代码

<servlet>
	<servlet-name>regservlet-name>
	<servlet-class>web.RegServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>regservlet-name>
	<url-pattern>/regurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第9张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第10张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第11张图片

九、Servlet运行原理

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第12张图片

十、请求方式

1.什么是起你去方式?

  • 就是浏览器向服务器发送数据的方式
  • 我们需要掌握众多方式中的2种:GET+POST

2.GET

  • 采用请求路径传参
  • 参数在传递过程中可见,导致隐私性差
  • 路径可以容纳的数据有限,只能传少量数据

所有的请求默认都是GET请求

3.POST

  • 采用实体内容传参
  • 参数在传递过程中不可见,隐私性好
  • 实体内容专门用来传数据,大小没有限制

在form上加method=“post”

4.观察GET和POST请求

  • 在浏览器上按快捷键F12
  • 看NetWork选项

5.GET和POST使用场景(建议)

  • 查询数据时用GET,因为通常查询条件较少
  • 提交数据(表单)时用POST,因为通常提交的数据较多。

十一、乱码解决方案

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第13张图片

补充:

JavaBean

满足如下规范的类

  • 有包
  • 有默认的构造器
  • 实现序列化接口
  • 有get/set方法

十二、模拟查询员工案例

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第14张图片

1. Emp.java实体类

package entity;

import java.io.Serializable;
/**
 * 建议:
 * 1.尽量使用封装类型,因为它比基本类型多了null
 * 2.使用java.sql包下的日期,因为JDBC支持这样的日期类型
 *
 */
public class Emp implements Serializable {

	private Integer empno;
	private String ename;
	private String job;
	private Double sal;
	
	public Integer getEmpno() {
		return empno;
	}
	public void setEmpno(Integer empno) {
		this.empno = empno;
	}
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	public Double getSal() {
		return sal;
	}
	public void setSal(Double sal) {
		this.sal = sal;
	}
	
}

2. EmpDao.java接口

package dao;

import java.util.List;
import entity.Emp;

public interface EmpDao {

	List<Emp> findAll();
	
	void save(Emp e);
}

3. EmpDaoImpl.java

package dao;

import java.util.ArrayList;
import java.util.List;

import entity.Emp;

public class EmpDaoImpl implements EmpDao {

	public List<Emp> findAll() {
		//模拟查询所有的员工
		List<Emp> list = new ArrayList<Emp>();
		
		Emp e1 = new Emp();
		e1.setEmpno(1);
		e1.setEname("唐僧");
		e1.setJob("领导");
		e1.setSal(9000.0);
		list.add(e1);
		
		Emp e2 = new Emp();
		e2.setEmpno(2);
		e2.setEname("悟空");
		e2.setJob("职员");
		e2.setSal(5000.0);
		list.add(e2);
		
		Emp e3 = new Emp();
		e3.setEmpno(3);
		e3.setEname("八戒");
		e3.setJob("职员");
		e3.setSal(6000.0);
		list.add(e3);
		
		return list;
	}

	//模拟增加一个员工(此用于后面增加员工案例)
	public void save(Emp e) {
		System.out.println("增加了员工: " + e.getEname());
	}
}

4. FindEmpServlet.java

package web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

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

import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;

public class FindEmpServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, 
			HttpServletResponse res) 
			throws ServletException, IOException {
		//1.接收参数
		//2.处理业务(查询)
		EmpDao dao = new EmpDaoImpl();
		List<Emp> list = dao.findAll();
		//3.输出响应(表格)
		res.setContentType("text/html;charset=utf-8");
		PrintWriter w = res.getWriter();
		//当前: /EmpManager/findEmp
		//目标: /EmpManager/add_emp.html
		w.println("增加");
		//上面一行用于后面增加员工案例
		w.println("");
		w.println("	");
		w.println("		");
		w.println("		");
		w.println("		");
		w.println("		");
		w.println("	");//以下是表格数据if(list != null){for(Emp e : list){
				w.println("");
				w.println("	");
				w.println("	");
				w.println("	");
				w.println("	");
				w.println("");}}
		w.println("
编号姓名职位薪资
"+e.getEmpno()+""+e.getEname()+""+e.getJob()+""+e.getSal()+"
"
); w.close(); } }

5. web.xml

<servlet>
	<servlet-name>findEmpservlet-name>
	<servlet-class>web.FindEmpServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>findEmpservlet-name>
	<url-pattern>/findEmpurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第15张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第16张图片

十二、模拟增加员工案例

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第17张图片

1. AddEmpServlet.java

package web;

import java.io.IOException;
import java.io.PrintWriter;

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

import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;

public class AddEmpServlet extends HttpServlet {

	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		
		req.setCharacterEncoding("utf-8");
		
		//1.接收参数
		String ename = req.getParameter("ename");
		String job = req.getParameter("job");
		String sal = req.getParameter("sal");
		//2.处理业务:保存员工数据
		Emp e = new Emp();
		e.setEname(ename);
		e.setJob(job);
		if(sal != null && sal.equals("")) {
			e.setSal(new Double(sal));
		}		
		EmpDao dao = new EmpDaoImpl();
		dao.save(e);
		//3.发送响应
		res.setContentType("text/html;charset=utf-8");
		PrintWriter w = res.getWriter();
		w.println("

保存成功

"
); w.close(); } }

2. add_emp.html


<html>
<head>
<meta charset="UTF-8">
<title>增加员工title>
head>
<body>
	
	<form action="addEmp" method="post">
		<p>
			姓名:<input type="text" name="ename"/>
		p>
		<p>
			职位:<input type="text" name="job"/>
		p>
		<p>
			薪资:<input type="text" name="sal"/>
		p>
		<p>
			<input type="submit" value="保存"/>
		p>
	form>
body>
html>

3. web.xml 配置文件在加上一下代码

<servlet>
	<servlet-name>addEmpservlet-name>
	<servlet-class>web.AddEmpServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>addEmpservlet-name>
	<url-pattern>/addEmpurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第18张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第19张图片

注:此案例没连数据库,保存成功并不能真正的增加

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第20张图片

十三、重定向

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第21张图片

1. 修改AddEmpServlet.java

package web;

import java.io.IOException;

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

import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;

public class AddEmpServlet extends HttpServlet {

	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		
		req.setCharacterEncoding("utf-8");
		
		//1.接收参数
		String ename = req.getParameter("ename");
		String job = req.getParameter("job");
		String sal = req.getParameter("sal");
		//2.保存员工数据
		Emp e = new Emp();
		e.setEname(ename);
		e.setJob(job);
		if(sal != null && sal.equals("")) {
			e.setSal(new Double(sal));
		}		
		EmpDao dao = new EmpDaoImpl();
		dao.save(e);
		//3.发送响应
//		res.setContentType("text/html;charset=utf-8");
//		PrintWriter w = res.getWriter();
//		w.println("

保存成功

");
// w.close(); //重定向到查询页面,即 //建议浏览器自己去访问查询页面. //当前: /EmpManager/addEmp //目标: /EmpManager/findEmp res.sendRedirect("findEmp"); } }

增加员工提交后,会重定向到查询界面

十四、路径

1.什么是路径

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第22张图片

2.URI和URL的区别

1)侠义的理解

  • 只在Java项目中理解URI和URL
  • URI:绝对路径
  • URL:完整路径

从表面上看URI包含了URL

2)广义的理解

  • 在任意的WEB项目中理解URI和URL
  • URI:资源的名称
  • URL:资源的真名

URI包含了URL

3.如何配置Servlet访问路径

1)精确匹配

  • 举例: /abc
  • 只有/abc才能访问此Servlet
  • 此Servlet只能处理这一个请求

适合规模很小的项目

2)通配符

  • 举例: /*
  • 所有的路径的都能访问此Servlet
  • 此Servlet能处理所有请求

适合一个项目只写一个Servlet

3)后缀

  • 举例: *.hi
  • 表示所有以hi为后缀的请求都能访问此Servlet
  • 此Servlet能处理多个请求

适合一个项目写少量的几个Servlet

4)配置文件web.xml

<servlet>
	<servlet-name>abcservlet-name>
	<servlet-class>web.AbcServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>abcservlet-name>

	
	
	
	
	<url-pattern>*.dungurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第23张图片

4. 按规范处理路径修改员工查询、增加案例

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第24张图片

添加MianServlet.java

package web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

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

import dao.EmpDao;
import dao.EmpDaoImpl;
import entity.Emp;
/**
 * 路径规范:
 * 查询员工:/findEmp.do
 * 增加员工:/addEmp.do
 *
 */
public class MainServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest req, 
			HttpServletResponse res) 
			throws ServletException, IOException {
		//获取请求路径
		String path = req.getServletPath();
		//根据规范处理路径
		if("/findEmp.do".equals(path)) {
			findEmp(req,res);
		}else if("/addEmp.do".equals(path)) {
			addEmp(req,res);
		}else {
			//该异常抛给服务器,服务器可以统一处理
			throw new RuntimeException("查无此页");
		}
	}
	
	protected void findEmp(HttpServletRequest req, 
			HttpServletResponse res) 
			throws ServletException, IOException {
		//1.接收参数
		//2.处理业务(查询)
		EmpDao dao = new EmpDaoImpl();
		List<Emp> list = dao.findAll();
		//3.输出响应(表格)
		res.setContentType("text/html;charset=utf-8");
		PrintWriter w = res.getWriter();
		//当前: /EmpManager/findEmp
		//目标: /EmpManager/add_emp.html
		w.println("增加");
		w.println("");
		w.println("	");
		w.println("		");
		w.println("		");
		w.println("		");
		w.println("		");
		w.println("	");//以下是表格数据if(list != null){for(Emp e : list){
				w.println("");
				w.println("	");
				w.println("	");
				w.println("	");
				w.println("	");
				w.println("");}}
		w.println("
编号姓名职位薪资
"+e.getEmpno()+""+e.getEname()+""+e.getJob()+""+e.getSal()+"
"
); w.close(); } protected void addEmp(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); //1.接收参数 String ename = req.getParameter("ename"); String job = req.getParameter("job"); String sal = req.getParameter("sal"); //2.保存员工数据 Emp e = new Emp(); e.setEname(ename); e.setJob(job); if(sal != null && sal.equals("")) { e.setSal(new Double(sal)); } EmpDao dao = new EmpDaoImpl(); dao.save(e); //3.发送响应 // res.setContentType("text/html;charset=utf-8"); // PrintWriter w = res.getWriter(); // w.println("

保存成功

");
// w.close(); //重定向到查询页面,即 //建议浏览器自己去访问查询页面. //当前: /EmpManager/addEmp.do //目标: /EmpManager/findEmp.do res.sendRedirect("findEmp.do"); } }

修改web.xml配置文件(之前的注释掉)

<servlet>
	<servlet-name>mainservlet-name>
	<servlet-class>web.MainServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>mainservlet-name>
	<url-pattern>*.dourl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第25张图片

将add_emp.html中的action=“addEmp” 改成 action=“addEmp.do”

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第26张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第27张图片

十五、Servlet生命周期

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第28张图片

示例

以下几个案例都写在了Servlet3项目里了,目录结构如下

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第29张图片

HiServlet.java

package web;

import java.io.IOException;

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 HiServlet extends HttpServlet {
	public HiServlet() {
		System.out.println("实例化HiServlet");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		System.out.println("初始化HiServlet");
	}

	@Override
	protected void service(HttpServletRequest req, 
			HttpServletResponse res) 
			throws ServletException, IOException {
		System.out.println("调用HiServlet处理请求");
	}

	@Override
	public void destroy() {
		super.destroy();
		System.out.println("销毁HiServlet");
	}	
}

web.xml配置文件

<servlet>
	<servlet-name>hiservlet-name>
	<servlet-class>web.HiServletservlet-class>
	
	<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
	<servlet-name>hiservlet-name>
	<url-pattern>/hiurl-pattern>
servlet-mapping>

十六、ServletConfig和ServletContext

1.它们的作用

  • 都能够读取web.xml中为Servlet预置的参数

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第30张图片

2.它们的区别

1)config

  • config和Servlet是1对1的关系
  • Tomcat在初始化每个Servlet前会给它创建一个config
  • 调用HiServelt.init()前给他创建1个config
  • 调用HelloServlet.init()前给它创建1个config
  • 如果先给某个Servlet预置数据,使用config

2)context

  • context和Servlet是1对多的关系
  • Tomact在启动前就创建唯一的一个context
  • 所有的Servlet都可以共享这个对象中的数据
  • 如果想给多个Servlet预置数据,使用context

3.它们的应用

1)config(预置参数)

  • 假设要开发一个网页游戏,若超过人数上限则要排队
  • 登入时判断是否达到最大人数
  • 开发登录功能LoginServlet
  • 人数上限应该是一个可配置的参数maxOnline
  • 该参数由LoginServlet使用

由于该参数只是LoginServlet使用,由config读取即可

示例(登录上限)

LoginServlet.java

package web;

import java.io.IOException;

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 LoginServlet extends HttpServlet {

	//Tomcat创建Servlet的过程:
	//LoginServlet ls = new LoginServlet();
	//ServletConfig cfg = new ServletConfig();
	//ls.init(cfg);
	//ls.service();
	
	@Override
	public void init(ServletConfig config)throws ServletException {
		super.init(config);
		String maxOnline = config.getInitParameter("maxOnline");
		System.out.println(maxOnline);
	}	
	
	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		//此config就是init()传入的那个
		ServletConfig cfg = getServletConfig();
		String maxOnline = cfg.getInitParameter("maxOnline");
		System.out.println(maxOnline);
		System.out.println("正在登录...");
	}	
}

web.xml

<servlet>
	<servlet-name>loginservlet-name>
	<servlet-class>web.LoginServletservlet-class>
	
	<init-param>
		<param-name>maxOnlineparam-name>
		<param-value>3000param-value>
	init-param>
servlet>
<servlet-mapping>
	<servlet-name>loginservlet-name>
	<url-pattern>/loginurl-pattern>
servlet-mapping>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第31张图片

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第32张图片

2)context(分页)

  • 软件内有很多查询功能,都带有分页功能
  • 每页显示的行数size是常量,并且可配置
  • 该数据在多个查询功能之间共用,使用context读取

示例

FindDeptServlet.java

package web;

import java.io.IOException;

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

public class FindDeptServlet extends HttpServlet {

	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		//tomcat启动时就会创建唯一的context,并且会调用它的方法
		//加载web.xml中的公用参数,context是全局的,任何servlet都可以使用
		ServletContext ctx = getServletContext();
		String size = ctx.getInitParameter("size");
		System.out.println(size);
		System.out.println("分页查询部门数据");
		//统计流量
		//Integer count = (Integer)ctx.getAttribute("count");
		//ctx.setAttribute("count", ++count);
		//System.out.println(count);
	}
}

FindEmpServlet.java

package web;

import java.io.IOException;

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

public class FindEmpServlet extends HttpServlet {

	@Override
	protected void service(
		HttpServletRequest req, 
		HttpServletResponse res) throws ServletException, IOException {
		ServletContext ctx = getServletContext();
		String size = ctx.getInitParameter("size");
		System.out.println(size);
		System.out.println("分页查询员工数据");
		//统计流量
		//Integer count = (Integer)ctx.getAttribute("count");
		//ctx.setAttribute("count", ++count);
		//System.out.println(count);
	}
}

web.xml

<servlet>
	<servlet-name>findDeptservlet-name>
	<servlet-class>web.FindDeptServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>findDeptservlet-name>
	<url-pattern>/findDepturl-pattern>
servlet-mapping>

<servlet>
	<servlet-name>findEmpservlet-name>
	<servlet-class>web.FindEmpServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>findEmpservlet-name>
	<url-pattern>/findEmpurl-pattern>
servlet-mapping>


<context-param>
  	<param-name>sizeparam-name>
  	<param-value>20param-value>
context-param>

这里写图片描述

这里写图片描述

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第33张图片

4.context的特殊用法(context可以存取变量)

  • 前提:之前使用config和context读取的是常量
  • 而context还有能力读写变量
  • 用该对象读写的变量是可以被所有Servelt共用的
  • setAttribute()/getAttribute()
  • 案例:开发流量统计功能,无论访问哪个功能,流量+1
  • 由于流量是变量,并且在多功能间共用,所以用context

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第34张图片

示例

InitServlet.java

package web;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

/**
 * 此类仅仅是在服务器启动时初始化参数的,
 * 不负责处理任何具体的请求.
 * 一般web项目都要1-2个这样的servlet
 */
public class InitServlet extends HttpServlet {

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		//tomcat启动时会优先创建context,然后在创建Servlet
		ServletContext ctx = getServletContext();
		//流量默认为0
		ctx.setAttribute("count", 0);
	}
}

将FindDeptServlet.java和FindEmpServlet.java中统计流量的注释去掉

web.xml


<servlet>
	<servlet-name>initservlet-name>
	<servlet-class>web.InitServletservlet-class>
	<load-on-startup>1load-on-startup>
servlet>

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第35张图片

5.总结

  • 当需要给Servlet预置参数时使用这样的对象
  • 若参数只给一个Servlet使用,用config
  • 若参数给多个Servlet使用,用context

十七、Servlet层次结构

1.整体结构

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第36张图片

2.HttpServlet(我们一般重写黄色的service)

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第37张图片

十八、Servlet线程安全问题

1.同时修改局部变量

  • 局部变量存于栈内
  • 每个线程有自己的栈帧

此时没有线程安全问题

2.同时修改成员变量

  • 成员变量存于堆内
  • 所有线程共享这样的数据

此时存在线程安全问题

3.解决方案

  • 加锁

4.案例

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第38张图片

UpServlet.java

package web;

import java.io.IOException;
import java.io.PrintWriter;

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

public class UpServlet extends HttpServlet {
	
	double salary = 2000.0;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		//synchronized(this) {
			//模拟涨薪
			salary += 100.0;
			//网络延迟
			try {
				Thread.sleep(8000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//显示数据
			res.setContentType("text/html");
			PrintWriter out =  res.getWriter();
			out.println(salary);
			out.close();
		//}		
	}	
}

web.xml

<servlet>
	<servlet-name>upservlet-name>
	<servlet-class>web.UpServletservlet-class>
servlet>
<servlet-mapping>
	<servlet-name>upservlet-name>
	<url-pattern>/upurl-pattern>
servlet-mapping>

不加锁下

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第39张图片

加锁(把UpServlet.java中的代码注释去掉)

JavaEE之WEB项目开发(使用Servlet+Tomcat)_第40张图片

你可能感兴趣的:(我的java学习之旅)