JavaWeb——【Servlet】——一篇文章学会Servlet,值得你一看!

Servlet


1.概述

随着Web应用业务需求的增多,动态Web资源的开发变得越来越重要。目前,很多公司都提供了开发动态Web资源的相关技术,其中比较常见的有ASP、PHP、JSP和 Servlet等。
基于Java的动态Web资源开发,Sun公司提供了 Servlet和JSP两种技术接下来,接下来我们将学习Servlet的使用

2.Servlet接口

针对 Servlet 技术的开发,Sun公司提供了一系列接口和类,其中最重要的是javax.servlet. Servlet接口,Servlet就是一种实现了 Servlet 接口的类,它是由Web容器负责创建并调用,用于接收和响应用户的请求。在 Servlet 接口中定义了5个抽象方法,具体如下:

方法 功能
void init(ServletConfig config) 创建好Servlet对象后,会调用此方法,负责Servlet初始化工作
ServletConfig getServletConfig() 获取ServletConfig对象
String getServletInfo() 返回Servlet的信息
void service() 当容器接收到客户端的请求时,就会调用此方法,在该方法里,可以使用ServletRequest、ServletResponse,对象处理请求和响应
void destroy() Servlet对象被销毁时,此方法会被调用

3.Servlet快速入门(掌握)

3.1.第一步:编写一个类,实现Servlet接口

编写一个类,实现Servlet接口,重写5个方法。并在service() 方法里面添加输出
注意:这里的输出方向有两个了:
1.控制台:System.out.println("Hello Servlet");
2.浏览器:response.getWriter().write("Hello Service!!!");

public class HelloServlet implements Servlet {

	@Override
	public void destroy() {}

	@Override
	public ServletConfig getServletConfig() {
		return null;
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void init(ServletConfig config) throws ServletException {}

	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		//这是向控制台输出
		System.out.println("Hello Servlet");
		
		//向浏览器输出
		response.getWriter().write("Hello Service!!!");
	}
}

3.2.第二步:配置

在WebContent -> WEB-INF,web.xml文件下添加配置信息

<?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_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<!-- 先配置Servlet信息 -->
	<servlet>
		<!-- 配置Servlet名称,名称必须唯一 -->
		<servlet-name>HelloServlet</servlet-name>
		<!-- 配置Servlet的完整类名(包名+类名) -->
		<servlet-class>com.jf.weidong.HelloServlet</servlet-class>
	</servlet>

	<!-- 配置Servlet映射(访问路径) -->
	<servlet-mapping>
		<!-- 配置Servlet名称,值必须和<servlet-name>标签相同 -->
		<servlet-name>HelloServlet</servlet-name>
		<!-- 配置访问该Servlet的虚拟路径,正斜线(/)表示当前Web应用程序根目录 -->
		<url-pattern>/helloservlet</url-pattern>
	</servlet-mapping>
</web-app>

3.3.访问

访问的路径为:localhost:8080/项目名/servlet名字(url-patten节点配置的名字)
如上面的示例,路径为:http://localhost:8080/HelloServlet/helloservlet

输出结果:在这里插入图片描述

4.Servlet生命周期(熟悉)

在Java中,任何对象都有生命周期,Servlet也不例外
Servlet生命周期图
在这里插入图片描述

Servlet生命周期三个阶段
阶段一:初始化阶段(单例设计模式)
Servlet接收到请求后,会先检查内存中是否有该Servlet对象,如果有直接使用该对象,如果没有就创建实例,后调用init()方法,需要注意,在Servlet的整个生命周期内,它的init() 方法只会调用一次。
阶段二:运行阶段
Servlet生命周期中最主要的阶段,该阶段会为这个请求创建ServletRequest对象和ServletResponse对象,然后传递给service()方法,在整个Servlet生命周期内,每一次访问请求,都会创建新的ServletRequestServletResponse对象。并且调用service()方法
阶段三:销毁阶段
Servlet随着Web应用的销毁而销毁,在销毁Servlet之前,Servlet的destroy() 方法会被调用,在该方法里面可以进行资源释放操作,destroy()只会被调用一次,需要注意的是Servlet对象一旦被创建就会驻留在内存中,直到服务器关闭。

示例代码:

扫描二维码关注公众号,回复: 8611539 查看本文章
public class ServletDemo_life implements Servlet{
	/**
	 * Servlet实例被创建后,调用init方法进行初始化
	 * 	Servlet什么时候被创建呢?
	 * 		* 不是服务器一启动时,实例被创建,第一次访问的时候,实例才被创建。
	 * 	init方法调用几次呢?
	 * 		* 只被调用一次。
	 */
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init...");
	}
	/**
	 * service调用几次?
	 * 	* 有一次请求,调用一次service方法
	 */
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {
		System.out.println("service...");
	}
	/**
	 * Servlet实例什么时候被销毁?
	 * 	* 服务器关闭,手动移除。
	 * destroy调用几次
	 * 	* 一次	
	 */
	public void destroy() {
		System.out.println("destroy...");
	}
	public ServletConfig getServletConfig() {
		return null;
	}
	public String getServletInfo() {
		return null;
	}
}

打印

在这里插入图片描述

5.使用便捷类(掌握)

由于大多数Web应用都是通过HTTP和客户端进行交互,因此,在 Servlet接口中,提供了一个抽象类javax. servlet.http. HttpServlet,它是 GenericServlet的子类,专门用于创建应用于HTTP的 Servlet

5.1.HttpServlet类

抽象类,专门用于处理HTTP请求的Servlet

主要功能

  • 1.根据用户请求方式不同,定义相应的doXxx()方法处理用户请求。
  • 2.通过service()方法将HTTP请求和响应分别转为HttpServletRequest和HttpServletResponse类型的对象

使用步骤:

  • 1.新建类,基础HttpServlet
  • 2.重写doGet、doPost方法
  • 3.在web.xml文件中配置

示例:
编写一个类,继承HttpServlet类,演示doGet和doPost方法调用时机

public class HttpServletDemo extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		resp.getWriter().write("this is doGet !!!");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		resp.getWriter().write("this is doPost !!!");
	}
}

配置web.xml

<servlet>
	<servlet-name>HttpServletDemo</servlet-name>
	<servlet-class>com.jf.weidong.HttpServletDemo</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>HttpServletDemo</servlet-name>
	<url-pattern>/HttpServletDemo</url-pattern>
</servlet-mapping>

测试doGet方法
采用GET方式访问HttpServletDemo,只需要在地址栏输入HttpServletDemo访问地址即可打印this is doGet !!!

测试doPost方法
采用POST就必须使用表单了,创建表单提交html文件,设置提交数据到HttpServletDemo即可,主要代码如下:

<form action="/HelloServlet/HttpServletDemo" method="post">
	姓名:<input type="text" name="name">
	</p>
	年龄:<input type="text" name="name">
	</p>
	<input type="submit" value="提交">
</form>

访问效果

6.Servlet的其它操作

6.1.Servlet自动加载(了解)

有时候我们希望某些Servlet可以在Tomcat启动时随即启动,可以通过使用<load-on-startup>来完成

<load-on-startup>元素是<servlet>的一个子元素,用于指定Servlet被加载的时机和顺序。

使用方式

<servlet>
	<!-- 配置Servlet名称,名称必须唯一 -->
	<servlet-name>HelloServlet</servlet-name>
	<!-- 配置Servlet的完整类名(包名+类名) -->
	<servlet-class>com.jf.weidong.HelloServlet</servlet-class>
	<load-on-startup><!-- 值是正整数,值越小,越先被加载。 -->1</load-on-startup>
</servlet>

6.2.Servlet路径通配符(了解)

我们希望每个目录下的所有路径都可以访问同一个Servlet,这时,可以在Servlet映射的路径中使用通配符“*”
通配符的格式分为

格式为“ .扩展名 ”,例如“ .c ”匹配以“ .c ”结尾的所有URL地址
格式为“ /
”,例如 “ /abc/
” 匹配以“ /abc ”开始的所有URL地址
通配符优先级
有如下映射关系
Servlet1 映射到 /abc/*
Servlet2 映射到 /*
Servlet3 映射到 /abc
Servlet4 映射到 .do
当请求URL为/abc/a.html,“/abc/
”和“/”都匹配,Servlet1响应
当请求URL为/abc时,“/abc/
”和“/abc”都匹配,Servlet3响应
当请求URL为/abc/a.do时,“/abc/”和“.do”都匹配,Servlet1响应
当请求URL为/a.do时,“/”和“.do”都匹配,Servlet2响应
当请求URL为/xxx/yyy/a.do时,“/”和“.do”都匹配,Servlet2响应

6.3.默认Servlet(掌握)

如果某个Servlet的映射路径仅仅是一个正斜线(/),那么这个Servlet就是当前Web应用的默认Servlet,默认Servlet用于处理其它Servlet都不处理的访问请求。

如下配置,Servlet服务器在接收访问请求时,如果再web.xml文件中找不到匹配的

<servlet-mapping>元素的URL,就会将访问请求交给默认Servlet处理
<servlet>
	<servlet-name>DefaultServlet</servlet-name>
	<servlet-class>com.jf.weidong.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>DefaultServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>

6.4.Servlet多重映射(了解)

Servlet的多重映射指的是同一个 Servlet可以被映射成多个虚拟路径。也就是说客户端可以通过多个路径实现对同一个 Servlet的访问。配置方式有两种

6.4.1.方式一:配置多个servlet-mapping

如下代码,HttpServletDemo被映射到两个路径中,分别为:httpservletdemo1、httpservletdemo2

<!-- 第一个路径配置 -->
<servlet-mapping>
	<servlet-name>HttpServletDemo</servlet-name>
	<url-pattern>/httpservletdemo1</url-pattern>
</servlet-mapping>
<!-- 第一个路径配置 -->
<servlet-mapping>
	<servlet-name>HttpServletDemo</servlet-name>
	<url-pattern>/httpservletdemo2</url-pattern>
</servlet-mapping>

6.4.2.方式二:多个url-mapping

<servlet-mapping>
	<servlet-name>HttpServletDemo</servlet-name>
	<url-pattern>/httpservletdemo1</url-pattern>
	<url-pattern>/httpservletdemo2</url-pattern>
</servlet-mapping>

7.登陆案例(掌握)

在页面上输入用户名和密码,提交到服务器上,服务器拿着用户名和密码去数据库中查找有无此用户
若有用户,则提示登录成功
若无此用户,则提示用户名密码不匹配

技术分析:

  • 表单
  • servlet
  • 请求(request)
  • 响应(response)

7.1.登陆-表单

表单主要负责

  • 收集用户数据
  • 所有的字段要想提交到服务器必须有 name 属性
  • 提交的地址:action
  • 请求方式:post

7.2.登陆-Servlet

注意:此处用到了Request和Response对象,目前先不要深究这两个对象
编写处理登陆操作的Servlet,在此Servlet里面需要进行如下操作
1.接受参数:参数格式为key=value Sting value=request.getParameter("key")
例如:
http://localhost/day09/hello?username=tom request.getParameter("username")就可以获取tom值

2.回写内容(给客户端响应)
需要用到response response.getWriter().print("success");
可能会遇到乱码问题,处理中文乱码
resp.setContentType("text/html;charset=utf-8");//建议大家放在方法中的第一行

7.3.登陆-实现步骤

前期准备:

  • 使用数据库存储用户数据
  • 使用c3p0链接池,需要给出c3p0的配置文件
  • 使用dbutils简化数据库操作
  • 以上,所以需要导入三个jar包,将jar包拷贝到WebContent\lib目录下,如下图所示

在这里插入图片描述
c3p0配置文件

<c3p0-config>
	<!-- 命名的配置 -->
	<named-config name="jf">
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb1</property>
		<property name="user">root</property>
		<property name="password">123456</property>
		<!-- 如果池中数据连接不够时一次增长多少个 -->
		<property name="acquireIncrement">5</property>
		<property name="initialPoolSize">20</property>
		<property name="minPoolSize">10</property>
		<property name="maxPoolSize">40</property>
		<property name="maxStatements">20</property>
		<property name="maxStatementsPerConnection">5</property>
	</named-config>
</c3p0-config> 

7.3.1.添加数据库和数据

//初始化数据:
-- 用户表(user) 
CREATE TABLE user(
	id VARCHAR(255) NOT NULL PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR (20) DEFAULT NULL,
	password VARCHAR (20) DEFAULT NULL
);

INSERT INTO `user` VALUES ('dkdkd', 'admin', '123456');

7.3.2.创建登陆界面

action:设置表单提交的地址
提交方式为post

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<div align="center">
			<form action="http://localhost:8080/LoginDemo//login" method="post">
				用户名:<input type="text" name="username" /><br /> 密码:
				<input type="text" name="password" /><br />
				<input type="submit" value="登陆" />
			</form>
		</div>
	</body>
</html>

7.3.3.创建LoginServlet

LoginServlet里面主要处理用户提交过来的数据,以及给出响应
为了方便测试,现需要获取表单提交过来的用户名和密码数据,如下代码(只给出doPost方法代码)

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
	// 设置编码
	response.setContentType("text/html;charset=utf-8");

	// 获取用户名和密码
	String username = request.getParameter("username");
	String password = request.getParameter("password");

	System.out.println("username: " + username);
	System.out.println("password: " + password);
}

7.3.4.测试登陆界面和LoginServlet是否工作

访问登陆界面(地址是情况而定)
地址为:http://localhost:8080/LoginDemo/login.html
在这里插入图片描述

点击登陆按钮,查看控制台是否有输出
成功取到了提交过来的值
在这里插入图片描述

7.3.5.编写查询数据库逻辑

获取到提交过来的数据后,就需要查询数据库,看是否和数据库的数据匹配,并返回对应的结果
此时如果将查询数据库的代码写到LoginServlet类中,那么会造成LoginServlet非常臃肿,而且后期维护起来也非常困难
那有什么比较好的方式呢?
WEB三层架构

三层架构中的包结构

在这里插入图片描述

7.3.5.1.User实体类

三层架构一般都是从实体类开始写,在domain包中,新建User实体类,用来封装数据库查询到的数据

/**
 * 用户信息类
 * @author weidong
 */
public class User {
	/*
	 id varchar(255) primary key auto_increment,
	 username varchar(20),
	 password varchar(20),
	 */
	private String id;
	private String username;
	private String password;
	
	//为了篇幅,省略get/set方法
}
7.3.5.2.UserDao

编写好User类后,再在dao包下新建UserDao类,并添加查询数据库的方法,方法返回查询到的用户信息,如下代码所示

/**
 * 操作用户信息的Dao
 * @author weidong
 */
public class UserDao {
	/**
	 * 登录
	 * @param username 用户名
	 * @param password  密码
	 * @return 用户对象
	 * @throws SQLException
	 */
	public User getUserByUsernameAndPwd(String username, String password) throws SQLException {
		// 创建queryrunner
		QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());

		// 编写sql
		String sql = "select * from user where name = ? and password = ?";

		// 执行sql
		User user = qr.query(sql, new BeanHandler<>(User.class), username, password);
		return user;
	}
}

写好dao后,建议先进行测试(初期开发建议多测试),使用JUnit测试即可,新建测试类,编写测试方法,代码如下:

public class DaoTest {
	@Test
	public void t1(){
		UserDao userDao = new UserDao();
		try {
			User user = userDao.getUserByUsernameAndPwd("lisi", "123456");
			System.out.println(user);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

输出结果
在这里插入图片描述

7.3.5.3.UserService

编写好UserDao后,再编写业务逻辑层,现阶段登陆不考虑其它业务逻辑,所以不做过多的操作,添加login方法,并返回User对象,创建UserDao的实例,并调用查询的方法,代码如下

/**
 * 业务层
 * @author weidong
 */
public class UserService {
	/**
	 * 用户登录
	 * @param username 用户名
	 * @param password 密码
	 * @return User 用户
	 * @throws SQLException 
	 */
	public User login(String username, String password) throws SQLException{
		//调用dao
		UserDao dao=new UserDao();
		return dao.getUserByUsernameAndPwd(username,password);
	}
}

7.3.5.4.LoginServlet

编写好UserService类后,接下来就需要改动LoginServlet类了,在该类里面,需要实例化UserService,并调用响应的业务逻辑(login)方法获取到用户对象,并判断
如果用户对象为空,表示登陆失败(没有查询到数据)
如果用户对象不为空,表示登陆成功
关键代码如下:

如果User对象为空,那么直接使用response对象输出数据

User user = null;
try {
	user = new UserService().login(username, password);
} catch (SQLException e) {
	e.printStackTrace();
	throw new RuntimeException("网络异常,请稍后再试!");
}

// 3.判断user是否为空
if (user == null) {
	// 若为空 写"用户名和密码不匹配"
	response.getWriter().print("用户名和密码不匹配");
} else {
	// 若不为空 写"xxx:欢迎回来"
	response.getWriter().print(user.getUsername()+ ":欢迎回来");
}

完整代码

public class LoginServlet extends HttpServlet {
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 设置编码
		response.setContentType("text/html;charset=utf-8");

		// 获取用户名和密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");

		System.out.println("username: " + username);
		System.out.println("password: " + password);

		// 调用userservice 里的login(username,password) 返回值:User user

		User user = null;
		try {
			user = new UserService().login(username, password);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("网络异常,请稍后再试!");
		}

		// 3.判断user是否为空
		if (user == null) {
			// 若为空 写"用户名和密码不匹配"
			response.getWriter().print("用户名和密码不匹配");
		} else {
			// 若不为空 写"xxx:欢迎回来"
			response.getWriter().print(user.getUsername()+ ":欢迎回来");
		}
	}
}

测试-登陆成功
在这里插入图片描述

测试-登陆失败
在这里插入图片描述

7.3.6.添加定时返回功能

登陆失败后,需要添加【5秒后自动跳回登陆界面】的功能,此时就需要用到Refresh响应头
refresh 属性值:刷新与跳转(重定向)页面
refresh用于刷新与跳转(重定向)页面
refresh出现在http-equiv属性中,使用content属性表示刷新或跳转的开始时间与跳转的网址

在登陆失败的代码里面添加此响应头,5为时间值,url=xxx为跳转的地址。

在这里插入图片描述
运行效果
在这里插入图片描述

8.统计网站访问次数(掌握)

在一个用户登录成功之后,获取之前登录成功总人次,将次数+1,
并提供另外一个Servlet,显示登录成功的总人次

想要在Servlet中存储一些数据,可以使用ServletContext类

8.1.ServletContext

当 Servlet 容器启动时,会为每个 Web 应用创建一个唯一的 ServletContext对象代表当Web 应用,该对象不仅封装了当前 Web 应用的所有信息,而且实现了多个 Servlet 之间数据的共享。
服务器关闭的时候或者项目从服务器中移除 ServletContext 才会被销毁,如果将值保存在ServletContext中,值就有一个作用的范围,所以这个对象被称为”域对象”.

方法说明 功能描述
getAttributeNames() 获取放在ServletContext中所有的属性名
getAttribute(String name) 根据指定的属性名返回一个与之匹配的与属性值
removeAttribute(String name) 根据指定的域属性名,从ServletContext中删除匹配的域属性
setAttribute(String key,String value) 往ServletContext存入数据

8.2.实现步骤

  • 1.编写一个Servlet中的init方法,在init方法中初始化一个被登录次数0,将这个值存入到ServletContext域中,配置Servlet的load-on-startup(加载优先级)
  • 2.在登录成功代码中获得原来的次数+1,并再次回存到ServletContext域中
  • 3.登陆成功,访问CountServlet,从ServletContext域中获得次数,并且显示到页面上

8.3.代码实现

新建LoginServlet类,重写init()方法,在方法中初始化访问次数

public void init(ServletConfig config) throws ServletException {
	// 获得ServletContext对象,初始化一个值为0.
	ServletContext servletContext = this.getServletContext();
	servletContext.setAttribute("count", 0);
}

在登录成功的代码中获得原来的次数并且+1,回存到ServletContext域中。(主要代码)

// 3.判断user是否为空
if (user == null) {
	// 若为空 写"用户名和密码不匹配"
	response.getWriter().print("用户名和密码不匹配,5秒后自动跳转登陆界面");

	response.setHeader("refresh", "5;url=/LoginDemo/login.html");
} else {
	// 若不为空 写"xxx:欢迎回来"
	response.getWriter().print(user.getUsername() + ":欢迎回来");

	// 在登录成功的代码中获得原来的次数并且+1,存回到SErvletContext域中。
	// 登录成功的时候 获得原来的次数 + 1
	Integer count = (Integer) this.getServletContext().getAttribute("count");
	// 存回到ServletContext域中
	this.getServletContext().setAttribute("count", ++count);
}

显示登陆人数

public class CountServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 设置编码
		response.setContentType("text/html;charset=utf-8");

		// 获取全局管理者
		ServletContext context = this.getServletContext();

		// 获取登录的次数
		Integer count = (Integer) context.getAttribute("count");

		// 在页面上打印总次数
		response.getWriter().print("登录成功的总次数为:" + count);
	}
}

不要忘记配置

<servlet>
	<servlet-name>CountServlet</servlet-name>
	<servlet-class>com.jf.weidong.web.servlet.CountServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>CountServlet</servlet-name>
	<url-pattern>/countServlet</url-pattern>
</servlet-mapping>

测试
在这里插入图片描述

9.ServletContext获取资源(了解)

有时候希望读取Web应用中的一些资源文件,如配置文件、图片、文本等,在ServletContext接口中定义了一些读取Web资源的方法,这些方法是依靠Servlet容器来实现的。

方法说明 功能描述
Set getResourcePaths(String path) 返回一个Set集合,集合中包含资源目录中子目录和文件的路径名称参数path必须以正斜线(/)开始,指定匹配资源的部分路径
String getRealPath(String path) 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数path代表资源文件的虚拟路径,它应该以正斜线(/)开始,“/”表示当前Web(WebContent)应用的根目录,如果 Servlet容器不能将虚拟路径转换为文件系统的真实路径,则返回null
URL getResource(String path) 返回映射到某个资源文件的URL对象。参数path必须以正斜线(/)开始,“/”表示当前Web应用的根目录
InputStrean getResourceAsStream() 返回映射到某个资源文件的 InputStrean输入流对象,参数path传递规则和getResource()方法完全一致

示例代码
在src目录下创建一个资源文件(c3p0.properties),填入以下内容
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/jdbc
c3p0.user=root
c3p0.password=123456
注意:Eclipse/IDEA中 src 目录下创建的资源文件在Tomcat服务器启动时会被复制到WEB-INF/classes目录下

/**
 * 默认方式读取
 */
public class ServletContextReadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		ServletContext context = getServletContext();

		// 加载配置文件
		// InputStream in =
		// context.getResourceAsStream("/WEB-INF/classes/c3p0.properties");
		// Properties properties = new Properties();
		// properties.load(in);

		// 写法二:获取文件的路径
		String path = context.getRealPath("/WEB-INF/classes/c3p0.properties");

		// 加载配置文件
		InputStream in = new FileInputStream(path);
		Properties properties = new Properties();
		properties.load(in);

		String s = properties.getProperty("c3p0.driverClass") + "    " + properties.getProperty("c3p0.jdbcUrl") + "    "
				+ properties.getProperty("c3p0.user") + "    " + properties.getProperty("c3p0.password");

		PrintWriter writer = response.getWriter();
		writer.println(s);
	}
}

4.三层架构&MVC(理解)

三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为
界面层(User Interface layer)
业务逻辑层(Business Logic Layer)
数据访问层(Data access layer)。
区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。

4.1.三层架构划分

1.数据访问层DAO:主要看数据层里面有没有包含逻辑处理,实际上它的各个函数主要完成各个对数据文件的操作。而不必管其他操作。
2.业务逻辑层:主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。
3.表示层(界面层):主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。

包名一般为:

  • dao:数据访问层()
  • domain:管理javaBean实体对象(也可称为信息资源层)
  • service:业务逻辑层,通过使用dao层来对数据库进行操作
  • web:数据显示层

4.2.MVC模式

MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
这个模式认为,程序不论简单或复杂,从结构上看,都可以分成三层。
视图层(View)
数据层(Model)
控制层(Controller)
MVC并不是Java当中独有的,几乎所有的B/S的架构都采用了MVC框架模式,但是MVC在B/S架构中并没有完全地实现,其实我们根本不需要掌握未实现的部分。
1.控制层Controller:控制器即是控制请求的处理逻辑,对请求进行处理,负责请 求转发;
2.视图层View:视图即是用户看到并与之交互的界面,比如HTML(静态资源),JSP(动态资源)等等。
3.模型层Model:模型代表着一种企业规范,就是业务流程/状态的处理以及业务规则的规定。业务流程的处理过程对其他层来说是不透明的,模型接受视图数据的请求,并返回最终的处理结果。业务模型的设计可以说是MVC的核心
在这里插入图片描述

4.3.三层架构和MVC关系

三层架构是引用的体系(分层)结构,描述了整个引用的完整划分
MVC是一个设计模式,通常用于三层架构的展示层构建上。

5.ServletConfig(了解)

在Servlet运行期间,经常需要一些铺助信息,例如:程序的编码格式、用户名和密码等,这些信息可以在web.xml文件中使用 元素进行配置。

使用方法

<init-param>
   <!--- 节点参数名称 --->
<param-name>username</param-name>
   <!--- 参数值 --->
	<param-value>root</param-value>
</init-param>

ServletConfig 常用方法
String getInitParameter(String name):通过初始化参数name获取配置文件中初始化参数的value
Enumeration getInitParameterNames():获取初始化参数的名称们
String getServletName() :获取Servlet名称

演示使用ServletConfig获取初始化信息

<servlet>
    <servlet-name>ServletInitParam</servlet-name>
    <servlet-class>com.jf.weidong.ServletInitParam</servlet-class>
    <init-param>
    	<param-name>encoding</param-name>
    	<param-value>UTF-8</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>ServletInitParam</servlet-name>
    <url-pattern>/ServletInitParam</url-pattern>
</servlet-mapping>

Servlet

/**
 * 演示使用初始化参数
 * @author weidong
 */
public class ServletInitParam extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		ServletConfig config = this.getServletConfig();// 获取ServletConfig对象
		// 获取参数名字为encoding对呀参数值
		String encoding = config.getInitParameter("encoding");
		resp.getWriter().write(encoding);
	}
}

发布了230 篇原创文章 · 获赞 250 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/weixin_42247720/article/details/103791591
今日推荐