mybatis介绍+Tomcat介绍+servlet介绍

本文介绍了Mybatis的基础概念,包括简化JDBC、连接池、配置文件、映射过程。通过步骤详细展示了如何在项目中创建数据库、表和插入数据,配置mybatis全局配置及Mapper接口,演示了查询、新增、修改和删除操作,以及如何使用占位符和动态SQL。此外,还讲解了如何使用注解进行开发和单元测试框架的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1: Mybatis简介
1.1: 什么是mybatis
	Mybatis是由apache提供的一个针对持久层开源框架,对JDBC访问数据库的过程进行了简化和封装
	使用mybatis可以只关注SQL语句本身,而不需要关注(JDBC中的)注册驱动、获取连接、获取传输器、释放资源等过程。
	mybatis可以将要执行的SQL语句使用xml文件的方式或者注解方式配置起来,在执行时,将Java对象中携带的参数值和SQL骨架进行映射,生成最终要执行的SQL,将执行的结果处理后再返回。

1.2: mybatis的优势
	1)JDBC连接访问数据库有大量重复的代码,而mybatis可以极大的简化JDBC代码
	2)JDBC没有自带连接池,而mybatis自带的有连接池
	3)JDBC中是将SQL语句、连接参数写死在程序中,而mybatis是将SQL语句以及连接参数都写在配置文件中。
	4)JDBC执行查询后得到的ResultSet我们需要手动处理,而mybatis执行查询后得到的结果会处理完后,将处理后的结果返回。

2: Mybatis快速入门
2.1: 准备数据(创建yonghedb库,并在其中创建emp表,并往emp中插入8条记录)
	-- ------------------------------------------
	-- 1、创建数据库 yonghedb 数据库
	create database if not exists yonghedb charset utf8;
	use yonghedb; -- 选择yonghedb数据库
	-- 2、删除emp表(如果存在)
	drop table if exists emp;
	-- 3、在 yonghedb 库中创建 emp 表
	create table emp(
		id int primary key auto_increment,
		name varchar(50),
		job varchar(50),
		salary double
	);
	-- 4、往 emp 表中, 插入若干条记录
	insert into emp values(null, '王海涛', '程序员', 3300);
	insert into emp values(null, '齐雷', '程序员', 2800);
	insert into emp values(null, '刘沛霞', '程序员鼓励师', 2700);
	insert into emp values(null, '陈子枢', '部门总监', 4200);
	insert into emp values(null, '刘昱江', '程序员', 3000);
	insert into emp values(null, '董长春', '程序员', 3500);
	insert into emp values(null, '苍老师', '程序员', 3700);
	insert into emp values(null, '韩少云', 'CEO', 5000);
	-- ------------------------------------------

2.2: 创建项目、导入jar包、创建测试类
	1)创建一个maven的Java项目: CGB-Mybatis-01
	2)在项目的pom文件中导入mybatis的、mysql驱动的 以及 log4j的jar包
	-- ------------------------------------------
	<dependencies>
	    <!-- junit单元测试 -->
	    <dependency>
	        <groupId>junit</groupId>
	        <artifactId>junit</artifactId>
	        <version>4.9</version>
	    </dependency>
	    <!-- mysql驱动 -->
	    <dependency>
	        <groupId>mysql</groupId>
	        <artifactId>mysql-connector-java</artifactId>
	        <version>8.0.11</version>
	    </dependency>
	    <!-- mybatis -->
	    <dependency>
	        <groupId>org.mybatis</groupId>
	        <artifactId>mybatis</artifactId>
	        <version>3.2.8</version>
	    </dependency>
	    <!-- 整合log4j -->
	    <dependency>
	        <groupId>org.slf4j</groupId>
	        <artifactId>slf4j-log4j12</artifactId>
	        <version>1.6.4</version>
	    </dependency>
	</dependencies>
	-- ------------------------------------------
	3)创建一个 cn.tedu.MybatisTest01 类, 在这个类中查询emp表中的所有数据, 并将所有员工数据封装到Emp对象中, 最后将Emp对象封装到List集合中

	4)提供[mybatis-config.xml]文件, 在这个文件中配置事务管理方式, 以及连接数据库的基本信息, 以及是否使用连接池等
	mybatis-config文件头信息如下:
	---------------------------
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE configuration
	    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	    "http://mybatis.org/dtd/mybatis-3-config.dtd">
	    
	<!-- MyBatis的全局配置文件 -->
	<configuration>
	  
	</configuration>
	---------------------------
	mybatis-config.xml文件的完整内容如下:
	--------------------------------------------
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE configuration
	    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	    "http://mybatis.org/dtd/mybatis-3-config.dtd">
	    
	<!-- MyBatis的全局配置文件 -->
	<configuration>
		<!-- 1.配置开发环境 -->
		<environments default="dev">
			<environment id="dev">
				<!-- 1.1.配置事务管理方式
					JDBC: 将事务交给JDBC管理(mybatis会自动开启事务,但需手动提交)
					MANAGED: 自己手动管理事务 -->
				<transactionManager type="JDBC"></transactionManager>
				<!-- 1.2.配置连接池信息, type的取值:
					JNDI: 已过时
					UNPOOLED: 不使用连接池
					POOLED: 使用连接池(可以减少连接创建次数,提高执行效率) -->
				<dataSource type="POOLED">
					<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
					<property name="url" value="jdbc:mysql:///yonghedb?characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai"/>
					<property name="username" value="root"/>
					<property name="password" value="root"/>
				</dataSource>
			</environment>
		</environments>
		
		<!-- 2.导入XxxMapper.xml文件(如果mapper文件有多个,
			可以通过多个mapper标签导入)
			resource属性会直接到类目录(classes)下去找指定位置的文件
		 -->
		<mappers>
			<mapper resource="EmpMapper.xml"/>
		</mappers>
	</configuration>
	--------------------------------------------
	5)提供[EmpMapper.xml]文件, 在这个文件中可以配置我们想执行的任何SQL语句(查询,新增,修改,删除等)
	EmpMapper文件头信息如下:
	---------------------------
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE mapper
	  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
	<mapper namespace="">
	  
	  
	</mapper>
	---------------------------
	EmpMapper.xml文件的完整内容如下:
	--------------------------------------------
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE mapper
	  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	<!-- namespace: 用于标识当前这个mapper文件(就是一个名字)
		在mybatis程序中需要通过这个名字来定位当前这个mapper文件
		通过namespace值+id值可以定位要执行的是哪条SQL语句
	 -->
	<mapper namespace="EmpMapper">
	  <!-- 通过select,insert,update,delete标签来存放要执行的SQL -->
	  <!-- 练习01: 查询emp表中的所有员工信息 -->
	  <!-- 
	  	id属性:要求当前这个文件中的id值必须是独一无二的(不能重复)
	  	resultType属性: 指定查询的结果要存放在哪个类型的对象中
	   -->
	  <select id="findAll" resultType="cn.tedu.pojo.Emp">
	  	select * from emp
	  </select>
	  
	</mapper>
	--------------------------------------------
	6)提供一个 cn.tedu.pojo.Emp 类,用于封装查询的员工信息,Emp代码如下:
	--------------------------------------------
	public class Emp {
		//提供私有属性
		private Integer id;
		private String name;
		private String job;
		private Double salary;

		//提供属性对应的get和set方法
		public Integer getId() {
			return id;
		}
		public void setId(Integer id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getJob() {
			return job;
		}
		public void setJob(String job) {
			this.job = job;
		}
		public Double getSalary() {
			return salary;
		}
		public void setSalary(Double salary) {
			this.salary = salary;
		}
		//toString方法
		@Override
		public String toString() {
			return "Emp [id=" + id + ", name=" + name + ", job=" + job + ", salary=" + salary + "]";
		}
	}
	
	--------------------------------------------
	为了封装员工信息而提供的Emp类, 我们称之为实体类(简单java对象, POJO: Plain Ordinary Java Object)
	如果要查询所有的员工信息,员工信息查询出来后需要封装到Java对象中
	因此这里需要提供的Emp(员工)类,这个类用于封装所有的员工信息
	
	pojo(plain old/ordinary java object): 简单java对象
		如果一个类只是用来封装数据的(比如为了封装员工信息而提供的Emp类)
		这样的类我们称之为POJO类,通过该类生成的对象称之为POJO对象

	有哪些信息(数据)需要封装到Emp类中,就在Emp类中提供什么的属性/变量
	在Emp中提供4个变量(id、name、job、salary)分别用来封装emp表中的id、name、job、salary四列数据。
	再提供4个变量(id、name、job、salary)对应的Get和Set方法

	关于Emp实体类中的id和salary为什么不用int和double类型, 而是用Integer和Double类型
	因为int和double都属于基本类型, 基本类型的默认值(0, 0.0, 空字符,false )
	但如果使用包装类型, 包装类型的默认值是null, 可以避免一些误会产生

	重写toString:是为了在打印Emp对象时,输出的是对象中所存储的值,而不是输出地址值

	在编写实体类(POJO类)时,如果要添加有参构造函数,建议将无参构造函数也带上!
	--------------------------------------------
	7)完成 cn.tedu.MybatisDemo1中的代码, 并运行测试
	--------------------------------------------
	public class MybatisDemo01 {
		public static void main(String[] args) throws Exception {
			//1.读取mybatis核心配置文件中的配置信息(mybatis-config.xml)
			InputStream in = Resources.getResourceAsStream( "mybatis-config.xml" );
			//2.基于上面读取的配置信息获取SqlSessionFactory对象(工厂)
			SqlSessionFactory fac = new SqlSessionFactoryBuilder().build( in );
			//3.打开与数据库的连接(即通过工厂对象获取SqlSession对象)
			SqlSession session = fac.openSession();
			//4.通过namespace+id找到并执行SQL语句, 返回处理后的结果
			//EmpMapper.xml, List<Emp>
			List<Emp> list = session.selectList( "EmpMapper.findAll" );
			//5.输出结果
			for (Emp emp : list) {
				System.out.println( emp );
			}
		}
	}
	--------------------------------------------
	8)执行结果:
	--------------------------------------------
	log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).
	log4j:WARN Please initialize the log4j system properly.
	log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. -- 上面这些是log4j的警告信息, 不是异常, 也不是错误!!!
	Emp [id=1, name=王海涛, job=程序员, salary=3300.0]
	Emp [id=2, name=齐雷, job=程序员, salary=2800.0]
	Emp [id=3, name=刘沛霞, job=程序员鼓励师, salary=2700.0]
	Emp [id=4, name=陈子枢, job=部门总监, salary=4200.0]
	Emp [id=5, name=刘昱江, job=程序员, salary=3000.0]
	Emp [id=6, name=董长春, job=程序员, salary=3500.0]
	Emp [id=7, name=苍老师, job=程序员, salary=3700.0]
	Emp [id=8, name=韩少云, job=CEO, salary=5000.0]
	--------------------------------------------
2.3: mybatis程序中常见的问题:
	1) Emp类中添加了有参构造函数,但没有添加无参构造函数!	
		Mybatis底层会基于反射创建Emp类的对象实例, 创建时使用的就是Emp类的无参构造函数,如果没有无参构造函数,就会报错!
		错误信息: java.lang.NoSuchMethodException: cn.tedu.pojo.Emp.<init>()
		-- 经验总结: 在写实体类时如果要添加有参构造函数, 尽量将无参构造也加上!
		
	2) 执行SQL语句时, namespace或id写错了, 找不到要执行的SQL语句就会报错:
		每条SQL语句都有对应的 namespace+id, 而这些信息是存放在一个map中
			EmpMapper.findAll(key) : select * from emp(value)
		错误信息: Mapped Statements collection does not contain value for EmpMapper.finaAll

		如果mapper文件中标签的id值重复了, 将会报如下错误:
		错误信息: Mapped Statements collection already contains value for EmpMapper.update
	
		
	3) 连接数据库的基本信息书写错误, 会导致连接不上数据库:
		错误信息: DataSourceException: Unknown DataSource property: usename
		-- 报了一个未知的数据源(连接池)属性: usename
		
2.4: 如果emp表中的列名 和 Emp对象中的属性名不相同, 查询的结果能封装到Emp对象中吗?
	emp表中的列名是:empname, 	而Emp对象中的属性名是:name
	set方法: setEmpname		setName		方法不对应
	暴力反射: empname		name		属性名和列名也不对应
	所以数据没法封装!
	
	mybatis通过反射根据emp表中的列名(empname) 生成一个set方法: setEmpname
	去Emp对象中寻找这个setEmpname, 如果有就调用这个方法将 empname列中的值封装到Emp对象
	如果Emp对象中没有setEmpname方法, 就会根据列名(empname) 到Emp对象中寻找是否有同名的
	属性, 如果有, 会通过暴力反射将emp表中empname列的值赋值给同名的属性, 但其实也没有!

3: mybatis增删改操作
	1.新增员工信息: 赵云 保安 6000
	2.修改员工信息: 赵云 保镖 20000
	3.删除员工信息: 删除名称为'赵云'的员工信息
	-------------------------------------------------
	SqlSession session = null;
	/* @Before标记的方法会在 每个@Test标记的方法之前执行! */
	@Before
	public void beforeMethod() throws Exception{
		//1.读取mybatis核心配置文件中的配置信息(mybatis-config.xml)
		InputStream in = Resources.getResourceAsStream( "mybatis-config.xml" );
		//2.基于上面读取的配置信息获取SqlSessionFactory对象(工厂)
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build( in );
		//3.打开与数据库的连接(即通过工厂对象获取SqlSession对象)
		session = factory.openSession( true );
		//true: 表示自动提交事务, 默认是false, 表示关闭自动提交, 需要手动提交!
	}
	-------------------------------------------------
	<!-- 练习02:新增员工信息: 赵云 保安 6000 -->
	<insert id="insert">
		insert into emp value(null, '赵云', '保安', 6000 )
	</insert>
		
	/* 练习02:新增员工信息: 赵云 保安 6000 */
	@Test
	public void testInsert() {
		//通过namespace+id找到并执行SQL语句, 返回执行结果
		int rows = session.insert( "EmpMapper.insert" );
		System.out.println( "影响行数为: "+rows );
		//提交事务
		//session.commit();
	}
	-------------------------------------------------
	<!-- 练习03:修改员工信息: 赵云 保镖 20000 -->
	<update id="update">
		update emp set job='保镖', salary=20000 where name='赵云'
	</update>
	
	/* 练习03:修改员工信息: 赵云 保镖 20000 */
	@Test
	public void testUpdate() {
		//通过namespace+id找到并执行SQL语句, 返回执行结果
		int rows = session.update( "EmpMapper.update" );
		System.out.println( "影响行数为: "+rows );
	}	
	-------------------------------------------------
	<!-- 练习04:删除员工信息: 删除名称为'赵云'的员工信息 -->
	<update id="update">
		delete from emp where name='赵云'
	</update>
	
	/* 练习04:删除员工信息: 删除名称为'赵云'的员工信息 */
	@Test
	public void testDelete() {
		//通过namespace+id找到并执行SQL语句, 返回执行结果
		int rows = session.delete( "EmpMapper.delete" );
		System.out.println( "影响行数为: "+rows );
	}
	-------------------------------------------------
4: Mybatis的占位符
4.1.启用log4j日志框架
	Log4j是专门为Java语言提供的一个日志框架, 可以通过log4j打印程序中的日志信息
	mybatis默认已经支持了log4j框架, 我们在mybatis中使用log4j时, 只需要两步:
	1)导入log4j的jar包
	2)导入log4j的配置文件(log4j.properties)即可, 配置文件内容如下:
	-------------------------------------------------
	# Global logging configuration
	log4j.rootLogger=DEBUG, stdout
	# Console output...
	log4j.appender.stdout=org.apache.log4j.ConsoleAppender
	log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
	log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
	-------------------------------------------------
	# Global logging configuration
	log4j.rootLogger=DEBUG, Console, LOGFILE
	# Console output...
	log4j.appender.Console=org.apache.log4j.ConsoleAppender
	log4j.appender.Console.layout=org.apache.log4j.PatternLayout
	log4j.appender.Console.layout.ConversionPattern=%5p [%t] %d{yyyy-MM-dd hh:mm:ss} - %m%n

	log4j.appender.LOGFILE=org.apache.log4j.FileAppender
	log4j.appender.LOGFILE.file=./mylog.log
	log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
	log4j.appender.LOGFILE.layout.ConversionPattern=%5p [%t] %d{yyyy-MM-dd hh:mm:ss} - %m%n
	-------------------------------------------------

4.2: mybatis的占位符
	mybatis中有两种占位符, 分别是: #{}, ${}
	其中最常用的就是 #{} 占位符
	示例:
	-------------------------------------------------
	<!-- 练习05:新增员工信息: null, 马云, 教师, 800 -->
	<insert id="insert2">
		insert into emp value( null, #{name}, #{job}, #{salary} )
	</insert>

	/* 练习05:新增员工信息: null, 马云, 教师, 800 */
	@Test
	public void testInsert2() {
		//声明一个map集合,将SQL参数封装到map中
		Map map = new HashMap();
		map.put( "name", "马云" );
		map.put( "job", "教师" );
		map.put( "salary", 800 );
		//根据namespace+id找到SQL语句, 将map作为参数传过去, 并执行SQL语句
		int rows = session.insert( "EmpMapper.insert2", map );
		System.out.println( "影响行数: "+rows );
	}
	-------------------------------------------------
	<!-- 练习06: 修改员工信息: 将马云的职位改为"CEO", 薪资改为80000 -->
	<update id="update2">
		update emp set job=#{job}, salary=#{salary}
		where name=#{name}
	</update>

	@Test
	public void testUpdate3() {
		//将SQL语句中的参数封装到POJO对象中
		//Emp emp = new Emp(null, "马云", "教授", 8888.0);
		Emp emp = new Emp();
		emp.setName( "马云" );
		emp.setJob( "教授" );
		emp.setSalary( 8888.0 );
		//定位SQL并执行SQL
		session.update( "EmpMapper.update2", emp );
	}
	-------------------------------------------------
1、#{}占位符: 其实就是JDBC中的问号(?)占位符,在mybatis底层会将 #{}占位符翻译成问号(?)占位符
	如果在SQL语句中占位符只有一个#{}占位符,{}中名称没有要求, 但不能是空的; 参数可以直接传递,不用封装;
	如果在SQL语句中的#{}占位符,不止一个,参数值需要通过Map或者POJO对象进行封装;

	1)如果通过Map集合来封装SQL参数值,#{}占位符中的名称要和Map中的key保持一致!
	-------------------------------------------------
		//声明一个map集合,将SQL参数封装到map中
		Map map = new HashMap();
		map.put( "name", "马云" );
		map.put( "job", "教师" );
		map.put( "salary", 800 );
		//根据namespace+id找到SQL语句, 将map作为参数传过去, 并执行SQL语句
		int rows = session.insert( "EmpMapper.insert2", map );

		<!-- 练习05:新增员工信息: null, 马云, 教师, 800 -->
		<insert id="insert2">
			insert into emp value( null, #{name}, #{job}, #{salary} )
		</insert>
	-------------------------------------------------
		因为在mybatis底层是通过#{}占位符中的名称,作为key,到map中获取对应的value;
		
	2)如果通过POJO对象来封装SQL参数值,#{}占位符中的名称要在POJO对象中有对应的getXxx方法,或者有对应的变量
	-------------------------------------------------
		Emp emp = new Emp();
		emp.setName( "马云" );
		emp.setJob( "教授" );
		emp.setSalary( 8888.0 );
		//定位SQL并执行SQL
		session.update( "EmpMapper.update2", emp );
		
		<!-- 练习06: 修改员工信息: 将马云的职位改为"CEO", 薪资改为80000 -->
		<update id="update2">
			update emp set job=#{job}, salary=#{salary}
			where name=#{name}
		</update>
	-------------------------------------------------
		例如:#{job}占位符中的名称为job,那么就意味着,在Emp中要有getJob()方法或者有job变量,如果两者都有,会优先通过getXxx方法来获取POJO对象中存储的属性值,如果没有getXxx方法,会通过暴力反射直接获取Emp中job变量的值。

	总结: 在Mybatis框架中,大部分情况都是用#{}占位符,#{}其实就是JDBC中的问号(?)占位符,是为SQL语句中的【参数值】进行占位。例如:
		查询:select * from emp where job=参数值 and salary>参数值
		新增: insert into emp value(null, 参数值, 参数值, 参数值)
		修改: update emp set 列=参数值, 列=参数值, .. where 列=参数值...
		删除: delete from emp where 列=参数值...

2、${}占位符: 
	select * from emp where id>5;
	${}占位符: 是为SQL语句中的某一个SQL片段进行占位,将参数传递过来时,是直接将参数拼接在${}占位符所在的位置,因为是直接拼接,所以可能会引发SQL注入攻击,因此不推荐大量使用!
		如果SQL语句中只有一个#{}占位符,参数可以不用封装,直接传递即可!
		但如果SQL语句中哪怕只有一个${}占位符,参数也必须得先封装到Map或者POJO对象中,再把Map或者POJO对象传递过去!
		mybatis底层在执行SQL语句时,使用的就是PreparedStatement对象来传输SQL语句!
	-------------------------------------------------
	<!-- 练习09: 查询emp表中的所有员工信息, 动态显示要查询的列 -->
	<select id="findAll2" resultType="cn.tedu.pojo.Emp">
		select ${colName} from emp
	</select>

	/* 练习09: 查询emp表中的所有员工信息, 动态显示要查询的列
	 * select * from emp; "*"
	 * select id, name, job; "id,name,job"
	 */
	@Test
	public void testFindAll2() {
		Map map = new HashMap();
		map.put( "colName" ,  "name,job" );
		List<Emp> list = 
				session.selectList( "EmpMapper.findAll2", map );
		for (Emp emp : list) {
			System.out.println( emp );
		}
	}
	-------------------------------------------------
5: Mybatis的动态SQL
	if标签、where标签、foreach标签
	动态SQL指的是:SQL语句可以根据参数值的不同,来生成不同的SQL语句
	-------------------------------------------------
	如果在员工列表页面中可以根据员工的薪资区间查询员工信息
	如果不传最低薪资 和 最高薪资, 默认查询所有薪资的员工信息
		select * from emp;
	如果传了一个最低薪资, 但没有传最高薪资: 
		select * from emp where salary > 最低薪资
	如果传了一个最高薪资, 但没有传最低薪资:
		select * from emp where salary < 最高薪资 
	如果既传了最低薪资, 也传了最高薪资: 
		select * from emp where salary<最高薪资 and salary>最低薪资

	1)if标签: 如果test属性中的布尔表达式为true, 那if标签中的SQL片段就会参与整个SQL语句的执行, 反之, 如果test属性中的布尔表达式为false, 那么if标签的中内容将不会执行!
		<if test="布尔表达式">
			SQL片段
		</if>
	-------------------------------------------------
	<!-- 练习10: 根据员工的薪资区间查询员工信息 -->
	<select id="findBySal" resultType="cn.tedu.pojo.Emp">
		select * from emp
		where 1=1
			<if test="minSal != null">
				and salary > #{minSal} 
			</if>
			<if test="maxSal != null">
				and salary &lt; #{maxSal} 
			</if>
	</select>

	/* 练习10: 根据员工的薪资区间查询员工信息 */
	@Test
	public void testFindBySal() {
		Map map = new HashMap();
		map.put( "minSal" , 3000 );
		map.put( "maxSal" , 4500 );
		
		List<Emp> list = session.selectList( "EmpMapper.findBySal", map );
		for (Emp emp : list) {
			System.out.println( emp );
		}
	}
	-------------------------------------------------
	2)where标签: 将if标签以及其中的条件都包裹在where标签内部, 只要有任何一个条件成立, where标签就会生成where关键字, 并且如果条件前面有多余的连接词(比如or,and),where标签会将多余的连接词去掉!
	
	<select id="findBySal2" resultType="cn.tedu.pojo.Emp">
		select * from emp
		<where>
			<if test="minSal != null">
				salary > #{minSal} 
			</if>
			<if test="maxSal != null">
				and salary &lt; #{maxSal} 
			</if>
		</where>
	</select>

	@Test
	public void testFindBySal2() {
		Map map = new HashMap();
		//map.put( "minSal" , 3000 );
		map.put( "maxSal" , 4500 );
		
		List<Emp> list = session.selectList( "EmpMapper.findBySal2", map );
		for (Emp emp : list) {
			System.out.println( emp );
		}
	}

	-------------------------------------------------
	3)foreach标签
		foreach标签可以对传过来的数组或集合进行遍历,生成我们所需要的SQL片段
			collection属性:如果传过来的只有一个数组(或List集合) collection指定的值则为array(或list); 如果传过来的是一个map集合, 将数组或集合作为value封装到map中, collection属性的值就是数组或集合在map中的key;
			open属性:指定所生成SQL片段的起始符号,通常是左圆括号 (
			close属性:指定所生成SQL片段的结束符号,通常是右圆括号 )
			item属性:指定占位符中的名称
			separator属性:指定占位符中间的分隔符, 通常是逗号 ,
		
	-------------------------------------------------
	案例1:根据员工的id批量删除员工信息 id数组 int ids = {1,3,5,7};
	<!-- 练习12: 根据员工的id批量删除员工信息 id数组 int[] ids = {1,3,5,7};
		delete from emp where id in(1,3,5,7)
		delete from emp where id in(?, ?, ?, ?)
	 -->
	<delete id="deleteByIds">
		delete from emp where id in
		<foreach collection="list" open="(" item="id" separator="," close=")">
			#{id}
		</foreach>
	</delete>

	/* 练习12: 根据员工的id批量删除员工信息 id数组 int[] ids = {1,3,5,7}; */
	@Test
	public void testDeleteByIds() {
		//int[] ids = {1,3,5,7}; //从页面上传过来的员工的id数组
		List list = new ArrayList();
		list.add( 2 );
		list.add( 4 );
		list.add( 6 );
		list.add( 8 );
		session.delete( "EmpMapper.deleteByIds", list );
	}
	-------------------------------------------------
	案例2:根据员工的id批量更新员工信息 id数组 int ids = {2,4,6,8} 1000;
	-------------------------------------------------
	<!-- 练习13: 根据员工的id批量更新员工的薪资,
		id数组 int[] ids = {2,4,6,8} 1000;
		map.put("arrayIds", ids);	
		map.put("money", 1000);	
	 -->
	<update id="updateByIds">
		update emp set salary=salary + #{money}
		where id in
		<foreach collection="arrayIds" open="(" item="id" separator="," close=")">
			#{id}
		</foreach>
	</update>

	/* 练习13: 根据员工的id批量更新员工的薪资,
		id数组 int[] ids = {2,4,6,8} 1000;
		map.put("arrayIds", ids);	
		map.put("money", 1000);	 */
	@Test
	public void testUpdateByIds() {
		int[] ids = {2,4,6,8}; //要更新的员工的id数组
		Double money = 1000.0; //要涨的薪资
		Map map = new HashMap();
		map.put( "arrayIds" , ids );
		map.put( "money" , 1000 );
		session.update( "EmpMapper.updateByIds", map );
	}
	-------------------------------------------------

6: Mybatis的Mapper接口开发
	mapper接口开发要满足以下四个规则:
	1)写一个接口, 要求接口的全类名(包名.接口名) 要等于 XxxMapper文件的namespace值
		namespace = 接口的全类名
	2)mapper文件中要执行的SQL语句, 在接口中得有对应的接口方法, 并且, SQL语句的id值要等于接口的这个方法名
		SQL标签的id值 = 方法名
	3)如果是查询SQL, resultType指定的类型要和接口方法的返回值类型对应
		a)如果接口返回的是某一个实体对象(Emp), 此时resultType指定的是该对象的类型(cn.tedu.pojo.Emp)
		b)如果接口返回的是集合(List<Emp>), 此时resultType指定的是集合中的泛型(cn.tedu.pojo.Emp)
	4)(可以忽略) SQL标签上的参数类型(paramterType属性)要和 接口方法的参数类型保持一致!
	-------------------------------------------------
	mapper接口开发测试1: 查询emp表中的所有员工信息
	1)提供一个接口: cn.tedu.dao.EmpMapper, 将EmpMapper.xml文件中的namespace值改为接口的全类名
		//接口的全类名: cn.tedu.dao.EmpMapper
		public interface EmpMapper {
			
		}
		namespace值: <mapper namespace="cn.tedu.dao.EmpMapper">
	2)要执行的SQL语句的id值 要和接口中的方法名保持一致
		<select id="findAll" resultType="cn.tedu.pojo.Emp">
			select * from emp
		</select>

		public interface EmpMapper {
			/* 练习01: 查询emp表中的所有员工信息 */
			public List<Emp> findAll();
		}
	3)resultType指定的类型要和接口方法的返回值类型对应
		<select id="findAll" resultType="cn.tedu.pojo.Emp">
			select * from emp
		</select>
		由于上面查询的emp信息结果可能不止一条, 所以返回的结果需要使用List集合进行封装
		public List<Emp> findAll();
	4)SQL语句中没有占位符, 也就不需要传参数, 因此接口方法也就不需要参数!
	
	-------------------------------------------------
	模拟mybatis提供的EmpMapper接口的实现类,代码如下:
	public class EmpMapperImpl implements EmpMapper{
		private SqlSession session;
		//将session对象通过构造方法保存到类的内部
		public EmpMapperImpl( SqlSession session ) {
			this.session = session;
		}
		
		/* 查询所有的员工信息 */
		public List<Emp> findAll() {
			/*
			获取当前这个类的父接口的全类名(=namespace)
			通过当前类的对象(this)获取当前类的字节码对象, 再通过当前类的字节码对象获取当前类实现的所有
			父接口组成的数组, 由于当前类实现的接口只有一个, 所有通过数组[0]获取当前类实现的接口
			再通过接口获取接口的全类名(包名.接口名)
			*/
			String interName = this.getClass().getInterfaces()[0].getName();
			//获取当前方法的名字(=SQL标签的id值)
			/*
			获取存放的方法调用栈信息(也就是所有方法的调用信息), 返回的是一个数组, getStackTrace
			这个方法会在栈顶(也就是数组的第一个元素), 调用这个方法的是findAll方法, 这个方法在数组中的
			第二个位置(也就是数组的第二个元素)
			 */
			StackTraceElement[] st = Thread.currentThread().getStackTrace();
			/*
			通过数组的中的第二个元素(其中方法所属类的全类名,方法名,当前方法所属文件的名字,也就方法调用的行数)
			获取当前调用的方法的名字
			 */
			String methodName = st[1].getMethodName();
			List<Emp> list = session.selectList( interName+"."+methodName );
			
			//System.out.println("----------------------------");
			//for (StackTraceElement stackTraceElement : st) {
			//	System.out.println( stackTraceElement );
			//}
			//System.out.println("----------------------------");
			//System.out.println("下面获取方法调用栈数组中第二个元素中的所有信息: ");
			//System.out.println( "获取当前方法的类名:"+st[1].getClassName() );
			//System.out.println( "获取当前方法的名字:"+st[1].getMethodName() );
			//System.out.println( "获取当前方法所属的文件名:"+st[1].getFileName() );
			//System.out.println( "获取当前方法调用的行数:"+st[1].getLineNumber() );
			//System.out.println("----------------------------");
			return list;
		}

		@Override
		public void insert() {
			//获取当前这个类的父接口的全类名(=namespace)
			String interName = this.getClass().getInterfaces()[0].getName();
			//获取当前方法的名字(=SQL标签的id值)
			StackTraceElement[] st = Thread.currentThread().getStackTrace();
			String methodName = st[1].getMethodName();
			session.insert( interName+"."+methodName );
		}

	}

	测试自己提供的EmpMapper接口的实现类(EmpMapperImpl)
	-------------------------------------------------
	/* 测试自己提供的EmpMapper接口的实现类: 新增员工信息 */
	@Test
	public void testInsert2() {
		//获取EmpMapper接口的子类(我们自己提供)的对象实例
		EmpMapper mapper = new EmpMapperImpl(session);
		mapper.insert();
	}
	
	/* 测试自己提供的EmpMapper接口的实现类(EmpMapperImpl) */
	@Test
	public void testFindAll2() {
		//获取EmpMapper接口的子类(我们自己提供)的对象实例
		EmpMapper mapper = new EmpMapperImpl(session);
		List<Emp> list = mapper.findAll();
		for (Emp emp : list) {
			System.out.println( emp );
		}
	}
	-------------------------------------------------
7: mybatis的注解开发
	使用xml方式和注解开发的区别?
	1)使用xml方式配置SQL语句,写起来相比注解要麻烦一些; 而注解方式,不用写配置文件,直接在接口的方法上面添加一个注解(@Select,@Insert,@Update,@Delete..),将SQL语句直接写在注解的括号里即可;
	2)使用注解方式配置SQL语句又回到将SQL语句写在Java程序中,如果将来SQL语句一旦发生变化,就意味着要修改java源文件(.java),改完后要重新编译整个项目,再打包、部署到服务器上,相比来说较为麻烦。

	1.由于使用注解开发,要将SQL语句配置在注解中,因此EmpMapper.xml文件也就不需要了,在mybatis-config.xml文件中也就不需要引入EmpMapper.xml文件了
	2.在mybatis-config.xml文件中引入SQL语句所在的mapper接口(因为SQL语句存放在接口中)
		<mappers>
			<!-- <mapper resource="EmpMapper.xml"/> -->
			<!-- 
				可以将每一个XxxMapper接口通过一个mapper标签的class属性引入
				如果有多个XxxMapper接口,添加多个mapper标签引入即可!
			 -->
			<!-- <mapper class="cn.tedu.dao.EmpMapper"/> -->
	
			<!-- 
				或者是直接引入XxxMapper接口所在的包, 这样mybais会直接扫描这个包下的
				所有接口中的每个方法, 那么这些方法上所配置的SQL语句也会被读取到mybatis中
			 -->
			<package name="cn.tedu.dao"/>
			
		</mappers>
	3.将SQL语句移动到EmpMapper.java接口中
	-------------------------------------------------
	//接口的全类名: cn.tedu.dao.EmpMapper
	public interface EmpMapper {
		
		/* 练习01: 查询emp表中的所有员工信息 */
		@Select("select id,name,job from emp")
		public List<Emp> findAll();
		
		/* 练习02: 新增员工信息(没有占位符) */
		@Insert("insert into emp value(null, '赵云云', '高级Java工程师', 35000)")
		public void insert();
		
		/* 练习05:新增员工信息: null, 马云, 教师, 800(有占位符) */
		@Insert("insert into emp value(null, #{name}, #{job}, #{salary})")
		public void insert2(Map map);
		
		/* 练习06: 修改员工信息: 将马云的职位改为"CEO", 薪资改为80000(有占位符) */
		@Update("update emp set job=#{job}, salary=#{salary} where name=#{name}")
		public void update2(Emp emp);
		
	}
	-------------------------------------------------
	4.测试(由于这里只是将SQL语句从XxxMapper.xml文件中移动到了XxxMapper接口中, 所以测试代码直接使用之前的即可!)

8: 补充内容
	单元测试框架(junit): 这个框架可以在不提供main函数, 并且不创建对象的情况下, 直接运行一个非静态的方法
	
	@Test注解可以标记一个非静态的方法, 在不添加main函数并且不创建对象的情况下直接运行这个方法, 但被@Test标记的方法必须符合以下要求:
		1)方法必须是公共的(pubilc), 不能是私有的(private)
		2)方法必须是非静态的(no static)
		3)方法必须是无返回值的(no return)
		4)方法必须是无参数的(no param)
	如果违反以上任何一个规则, 就会报如下异常:
		java.lang.Exception: No tests found matching [{ExactMatcher:...

 

========================================
>> tomcat服务器
========================================
一、服务器相关概念
1、什么是服务器
	服务器:分为软件服务器和硬件服务器
	硬件服务器:运行在互联网上的、具有静态IP的一台计算机(通常配置比较高)
	软件服务器:运行在互联网上的计算机程序(软件),将服务器软件安装在硬件服务器上,才可以对外提供服务。
		服务器软件分为很多种:数据库服务器(MySQL,Oracle,SQL Server等),Web服务器(tomcat,jetty,jboss等),邮件服务器,FTP服务器。。。
	
2、什么Web服务器
	Web服务器: 运行在互联网上的计算机程序,专门用于接收客户端(主要指浏览器)的请求,根据请求进行处理,最后给出回应!
	比如:打开浏览器,输入"http://www.baidu.com"回车,其实访问的就是百度的服务器,此时会向百度服务器发送一个请求,请求百度的首页,百度服务器会接收并处理这个请求,根据请求给出回应(将百度首页响应给客户端浏览器)
	
	tomcat就是一个Web服务器,特点是:小巧灵活,简单易用,学习成本非常低!


二、Tomcat服务器下载、安装、启动、配置
1、下载tomcat服务器
	下载地址: http://tomcat.apache.org
	tomcat分为很多版本,有windows版本(解压版和安装版)、linux版本
	推荐使用解压版(需要用的时候解压一份,不需要用了直接删除解压的目录即可!)
	
2、tomcat的安装、启动、配置
2.1.安装tomcat
	安装:解压之后就可以使用(安装的路径中最好不要包含中文和空格)
	
	在启动tomcat之前,需要配置(检查)一个JAVA_HOME环境变量,该变量需要指向JDK的安装根目录
	变量名:JAVA_HOME
	变量值:D:\software\Java\jdk1.8.0_161 (此处换成你安装的JDK的根目录)
	由于tomcat服务器是由Java语言开发的,所以运行tomcat需要JDK的支持
	JAVA_HOME这个变量就是在告诉tomcat服务器,需要使用哪一个位置上的JDK.
	
2.1.启动tomcat
	启动tomcat: 通过[tomcat安装目录]/bin/startup.bat文件可以启动tomcat服务器;
	关闭tomcat: 通过[tomcat安装目录]/bin/shutdown.bat文件可以关闭tomcat服务器;
			或者直接点击右上角的叉号
			
	启动tomcat之后,可以打开浏览器,访问: 
		http://localhost:8080
		http://127.0.0.1:8080
		
	如果可以访问到tomcat服务器的主页,就说明tomcat安装并且启动成功了!

3.修改tomcat服务器默认端口
	如果不修改端口,每次在访问tomcat服务器时,都需要在[主机名/ip地址]的后面加上:8080
	如果想在访问时,在主机名或ip地址后面省略端口,可以将端口修改为80(这个端口特殊,可以省略不写!)
	
	修改端口的方法是:
		找到[tomcat安装目录]/conf/server.xml并用文本编辑工具打开这个文件
		找到文件的69行,将Connector标签上的port属性值改为80,保存文件,并重启服务器即可生效!
	重启服务器后,就可以通过如下路径访问tomcat服务器:
		http://localhost:80
		http://localhost
		http://127.0.0.1:80
		http://127.0.0.1
	
三、tomcat服务器的目录结构(了解)
	bin: 存放批处理文件的目录(startup.bat、shutdown.bat文件)
	conf: 存放tomcat配置文件的目录(server.xml是tomcat核心配置文件)
	lib: 存放tomcat服务器在运行时所依赖的jar包的目录
	logs: 存在tomcat服务器在运行时产生的日志文件的目录
	temp: 存放tomcat服务器在运行时产生的临时文件的目录
	
	work: 存放tomcat服务器在运行期间产生的一些工作文件
		(JSP在第一次被访问时翻译后的Servlet文件、
		session对象序列化后产生的文件等都会放在这个目录下)
	webapps: 是Web应用的存放目录,放在这个目录中的Web应用程序,
		可以通过localhost虚拟主机进行访问
		webapps目录是localhost主机默认存放Web应用的目录
		把Web应用放在webapps目录下,就相当于发布到了localhost主机中
	
四、Web应用和虚拟主机

1、Web应用:
	Web应用其实就是一个目录,其中可以包含很多资源文件(html/css/js/图片/jsp/servlet..等)

    虚拟主机中不能直接管理Web资源文件(html/css/js/图片/jsp..等)
    需要将Web资源文件组织成一个Web应用(目录),将Web应用发布到虚拟主机中运行才可以被虚拟主机所管理

2、虚拟主机: 
	就是在tomcat服务器中配置的一个站点,在访问时就好像在访问一台真实独立的主机一样
	我们将这个站点称之为是,运行在tomcat服务器中的一台虚拟主机
    tomcat服务器中可以配置多个站点,每一个站点都是一台虚拟主机。
	下面是tomcat默认提供的localhost主机的配置:
	<Host name="localhost" appBase="webapps"...></Host>
	<Host name="www.baidu123.com" appBase="baidu"...></Host>
	========================================================
	1)在服务器硬件上安装了一个tomcat服务器软件
	2)在tomcat服务器软件内部可以配置多个站点(虚拟主机),其中tomcat默认自带了一个localhost虚拟主机。
	3)localhost虚拟主机默认管理Web应用的目录--webapps,发布到webapps目录下的web应用,也就都发布到了localhost主机中
	4)往webapps中发布了一个 jt web应用,其中包含一些Web资源文件
	5)web资源文件可以是(html/css/js/图片/servlet/jsp等)
	
五、Web应用
1、Web应用的目录结构
	news(目录,Web应用)
	 |-- 也可以将Web资源文件放在Web应用的根目录下
	 |-- 其它目录(放在其它目录中的资源文件可以被浏览器直接访问到)
	 |-- WEB-INF目录(隐私目录,放在这里面的资源文件,不能被浏览器直接访问)
	 		|-- classes目录(Java程序编译后的class文件会放在这个目录下)
	 		|-- lib目录(Web应用所依赖的jar包会放在这个目录下)
	 		|-- web.xml文件(当前Web应用的核心配置文件)
	
2、如何发布一个Web应用到虚拟主机中
	直接将Web应用的目录复制到虚拟主机所管理的目录下即可
	例如:将news复制到webapps目录下,由于webapps是localhost主机发布web应用的目录,
	所以相当于将news发布到了localhost主机中,可以通过localhost主机进行访问!


========================================
>> 导入已有的Maven项目(web项目,yonghe-ssm)
========================================
如何导入已有的Maven项目
1: 导入数据库(yonghedb)、表、表记录
	打开"yonghe-ssm项目"目录中的"SQL脚本.txt", 复制其中的SQL语句, 到Navicat中执行
	执行后会创建yonghedb库, 并创建 tb_door 表(门店表) 和 tb_order(订单表)
	
2:导入yonghe项目
	方式一: 通过import导入(只要是eclipse创建的项目, 任何项目都可以这样导入)
		1)点击eclipse左上角的"File" --> "Import...", 在弹出的窗口中找 "General" --> "Existing Project into Workspace"
		2)接着会切换到下一个窗口, 可以看到一个 "Select root directory"选项(选择根目录), 这行的后面有 "Browse..." 选项, 点击 "Browse..." 可以找到你要导入的项目, 点击你要导入的项目, 点击下方的 "选择文件夹"
		3)接着在窗口中间的位置 找到 "Copy Pojects into workspace" 选项并选中该选项, 选中该选项意味着: 导入的项目会复制到工作空间中一份(这样的好处是, 即使导入位置的项目删除了也不影响, 因为已经把整个项目复制到工作空间中了), 最后点击 "Finish" 完成即可!
		
	方式二: 创建新的项目, 将原项目中的代码复制到新项目中
		1)创建一个同类型的新的项目
			如果要导入的项目是Maven的Web项目,也就需要你创建一个Maven的Web项目
			这里新项目的名字可以 和原项目保持一致, 也可以不一致
		2)将原项目中的src目录复制到新项目中, 将新项目中的src目录覆盖即可

		3)如果是maven项目, 那么其中还有pom.xml文件, 将原项目中的 pom.xml 文件打开, 将其中需要的配置复制, 粘贴到新项目的pom文件中的对应位置即可!
		
3: 可能出现的问题
	1)导入项目后如果是 xxx.xml 文件报错, 这里的错误可以忽略, 是eclipse误报的!

	2)如果在导入项目后,有叹号(!),都是因为maven没有将所有的环境/依赖下载下来。
	可以通过如下三个步骤去解决:
		a)打开yonghe项目,找到其中的pom.xml文件,在文件中敲一个空白行并保存,让maven重新扫描pom文件,并根据其中的配置下载所需要的依赖;

		b)在报错的maven项目上右键--> Maven--> Update Project...,在弹出的窗口中勾选下方的
		[]Force Update...
		即勾选强制更新,如果还没有解决,再看第3步!

		c)下载老师下发的本地仓库(localRepo(maven的本地库).zip)
		用老师下发的本地仓库,替换自己的本地仓库!
		
	运行导入的yonghe项目,在项目上右键--> Run As --> Run On Server,在打开的浏览器地址栏后面补全路径: http://localhost:8080/yonghe/index
	/index对应的是controller中的一个方法,最后会跳转到index.jsp

========================================
>> Servlet
========================================
一、什么是Servlet
	Servlet 是由SUN公司提供的一门Web资源开发技术(规范,接口)
	Servlet是本质上是一个Java程序,但和我们之前接触的Java程序不同的是,
	Servlet无法独立运行(Servlet中没有main函数)
	需要将Servlet程序放在服务器中,由服务器调用才可以执行!
	
	运行在服务器中的Servlet程序作用是: 对服务器接收的请求进行处理(处理请求)

-------------------------------------------
Servlet3.1的jar包
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

Servlet2.5的jar包
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>
-------------------------------------------
	
二、开发Servlet程序
1、开发Servlet程序的步骤
	1)写一个类,需要实现一个Servlet接口或者继承Servlet接口的子类
		Servlet
		  |-- GenericServlet 实现了Servlet接口,并实现了其中的方法
		  			|-- HttpServlet 继承了GenericServlet,也实现了其中的方法
		在开发时,我们只需要继承HttpServlet,并继承其中的方法即可!
		
	2)在web.xml文件中配置Servlet对外访问的路径,再将Web应用发布到服务器即可!
		如果是Servlet3.0及以上版本, 可以使用注解方式配置Servlet访问路径
		
2、如何通过Eclipse创建一个Servlet程序

	1) Ctrl+N, 会弹出创建窗口, 在输入框中输入 "servlet" 进行搜索, 选中servlet, 点击 "Next"
		接着进入下一界面(其实这里和我们之前创建类几乎一样了, 区别就是这里默认会继承 HttpServlet )
	2) 填写包名和类名点击完成即可

	3) 创建好的类中有很多不需要的注释和构造方法实现, 删除即可!
		创建的Servlet类的内部保留 doGet 和 doPost 方法即可!	
	
3、运行Servlet程序
	第一种运行方式: 
		直接在要运行的文件(html/jsp/servlet等)上-->右键-->Run as-->Run On Server,
	eclipse会帮我们做如下几件事儿:
		1)将Servlet所在的Web项目(CGB-Servlet-01)发布到服务器中
		2)再启动tomcat服务器
		3)最后打开浏览器,在地址栏输入路径去访问这个Servlet
	Eclipse默认用内置浏览器去访问Servlet,但是这个内置浏览器有bug,最好是使用本地的浏览器去测试!
		
	第二种运行方式: 可以自己手动将项目发布到服务器、启动服务器、打开浏览器输入地址进行访问!
	
4、Servlet在web.xml文件中的配置
	全限定类名(全类名): 包名.类名 或者 包名.接口名 
	------------------------------------------
	<servlet>	
		<servlet-name>HelloWorld</servlet-name>
		<servlet-class>cn.tedu.HelloWorld</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloWorld</servlet-name>
		<url-pattern>/HelloWorld</url-pattern>
	</servlet-mapping>
	------------------------------------------
	1)每创建一个Servlet,eclipse会帮我们生成至少8行配置信息
		这8行配置信息由一个Servlet标签和一个servlet-mapping标签组成
		这两个标签中的<servlet-name>标签中的内容一致,决定了它俩是一组配置
	2)<servlet-class>标签中配置的当前Servlet类的全类名(包名.类名)
		将来服务器根据访问路径找到这个全类名,再利用反射+全类名可以获取当前Servlet类的实例	
	3)<url-pattern>标签中配置了外界该通过什么路径来访问当前Servlet。
		也就是说,这里配置什么路径,外界就得通过什么路径来访问这个Servlet!
	
	注意事项1: 如果不知道什么原因,tomcat服务器启动失败了,可以将Eclipse创建的Server删除,
		再重新创建一份(删除Server同时,也将左侧的Servers项目从工作空间中删除!)

	注意事项2: 在将tomcat和Eclipse整合之后,tomcat默认开启了热部署功能:
		在修改了代码后,不用重新发布,也不需要重启服务器,就可以运行最新的效果!
		(如果是创建了新的Servlet类,或者修改了web.xml文件,则需要重启服务器,才会生效!)

5、创建Servlet3.0或以上版本的项目
	在Servlet3.0的项目中, 可以通过注解方式配置Servlet相关信息
	------------------------------------------
	@WebServlet("/HelloWorld")
	public class HelloWorld extends HttpServlet{}
	------------------------------------------
	在@WebServlet这个注解内部所配置的内容就是(xml方式)url-pattern中配置的访问路径
	服务器通过扫描注解定位到当前这个Servlet,获取该类的全路径,
	通过全路径从硬盘上加载这个类到内存中,获取该类的字节码对象,再利用反射+字节码对象创建该类的实例,然后通过HelloWorld类的对象实例再调用其中的方法!

	代码示例:
	------------------------------------------
	@WebServlet("/HelloWorld")
	public class HelloWorld extends HttpServlet {
		private static final long serialVersionUID = 1L;
		//Http: GET和POST
		protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			//设置服务器发送数据以及浏览器接收数据的编码
			response.setContentType( "text/html;charset=utf-8" );
			//向浏览器响应数据
			response.getWriter().write( "世界, 你好!" );
		}
		protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			doGet(request, response);
		}
	}
	------------------------------------------
	

	
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值