Servlet对路径的处理
重定向
用户在浏览器输入一个地址,或者点击按钮触发一个请求地址,然后去往服务器端,此时服务端处理完相关计算后,再次向浏览器发送一个302状态和一个新的地址(比如www.baidu.com). 之后浏览器收到了302状态码和一个新的地址,然后浏览器就重新向这个新的地址发送请求。
302: 表示重定向, 当浏览器收到的状态码是302,表示需要重新发送请求,请求地址是和302一起过来的那个新的地址
适合的场景:
用户使用浏览器触发了一次请求后,然后服务端向浏览器发送一个新的地址,由浏览器自动再次发送一个请求。
比如:添加一个新员工后,然后页面自动显示所有员工信息,包含两次请求
第一次:insert, 用户主动触发的
第二次: select, 是服务端告诉浏览器再次触发
再比如: 登录成功后,跳转到主页面(所有员工信息) :
第一次: 登录验证(LoginServlet)
-- 调用DAO的checkLogin方法,返回true或者false
-- 如果登录成功,此时应该向浏览器发送响应数据(302,新地址appName/findAll)
第二次: 跳转到主页面(FindAllServlet)
-- 调用DAO的findAll方法,查询所有的员工信息,返回ResulSet
-- 遍历ResultSet ,然后使用流对象的println方法,拼接成一个table。
-- 响应对象将数据打包,返回给浏览器,浏览器解析成一个table
如何重定向
response.sendRedirect(String url)
url: 是重定向的新地址, 该地址可以是任意地址, 302状态码是响应对象自己设置的,不需要程序员设置
重定向的特点:
1. 重定向的地址可以是任何地址
2. 重定向后,浏览器的地址发生了变化
3. 重定向所涉及到的web组件并不共享同一个request和response
4. 重定向前,不可以关闭流 ,即不能调用 pw.close()
转发
什么是转发
一个web组件(servlet/jsp)将未完成的任务转交给另外一个web(servlet/jsp)组件。
如何转发
步骤1: 绑定数据
request.getAttribute("school","shuilidianli")
步骤2: 获取转发器,同时指定目的地的地址
RequestDispatcher rd = request.getRequestDispatcher("/servlet03");
步骤3: 开始转发,带上request和response对象
rd.forward(request,response);
转发的特点
转发是服务器的行为
浏览器在这个过程中只有一次行为,路径不会发生任何的变化
转发可以带有数据 request对象中
转发只能在当前项目中进行转发,不能转发外部资源
员工管理系统
员工列表界面的实现
第一步:创建java的项目(注意,是module) employee_v1
第二步:变成web项目
第三步:引入相关jar包,放入lib下
第四步:编写emp表的实体类Emp类型
第五步:编写emp表的Dao接口
package com.shuilidianli.employee.dao;
import com.shuilidianli.employee.entity.Emp;
import java.util.ArrayList;
/**
* 定义能想到的所有增删改查的方法
*/
public interface EmpDao {
/**
* 向数据库添加一个员工信息
* @param emp java的员工对象, 因为对象上有各个属性的信息
*/
void addEmp(Emp emp);
/**
* 将数据库中的某一个员工删除,通过员工编号
* @param id
*/
void delEmpById(int id);
/**
* 修改员工信息,通过员工编号定位某一个员工
* @param emp
*/
void modEmp(Emp emp);
/**
* 通过员工编号,查找该员工的所有信息
* @param id
* @return 返回的就是该员工的所有信息封装的Emp对象
*/
Emp findById(int id);
/**
* 查找所有的员工信息,将返回的每一个员工信息封装成Emp对象,并保存到集合中
* @return 集合对象
*/
ArrayList<Emp> findAll();
/**
* 分页查询,查询第page页的所有员工信息, 每页有pageSize条记录
* @param page 指定哪一页
* @param pageSize 每页的条数
* @return 返回指定页的所有员工信息
*/
ArrayList<Emp> findByPage(int page,int pageSize);
}
第六步:编写jdbc的配置文件,创建工具类,使用Druid连接池
第七步:编写EmpDao的实现类
第八步:编写员工列表的Servlet组件
第九步:编写web.xml
第十步:启动tomcat,进行测试
添加员工的功能实现
1)在web目录下,编写一个addEmp.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加员工信息页面</title>
</head>
<body>
<div>
<form action="addEmp" method="post">
员工编号:<input type="text" name="empno" placeholder="员工编号"> <br>
员工姓名:<input type="text" name="ename" placeholder="员工姓名"> <br>
员工职位:<input type="text" name="job" placeholder="员工职位"> <br>
领导编号:<input type="text" name="mgr" placeholder="领导编号"> <br>
入职日期:<input type="text" name="hiredate" placeholder="入职日期"> <br>
员工工资:<input type="text" name="salary" placeholder="员工工资"> <br>
员工奖金:<input type="text" name="bonus" placeholder="员工奖金"> <br>
部门编号:<input type="text" name="deptno" placeholder="部门编号"> <br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
2)编写AddEmp的组件
3)修改web.xml,新添加
<servlet>
<servlet-name>addEmp</servlet-name>
<servlet-class>com.shuilidianli.employee.web.AddEmp</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addEmp</servlet-name>
<url-pattern>/addEmp</url-pattern>
</servlet-mapping>
4)重新部署tomcat,进行测试
删除员工的功能实现
1)修改员工列表界面
2)修改web.xml,新添加一对配置信息
<servlet>
<servlet-name>delEmp</servlet-name>
<servlet-class>com.shuilidianli.employee.web.DelEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>delEmp</servlet-name>
<url-pattern>/delEmp</url-pattern>
</servlet-mapping>
3)创建对应的组件 DelEmp
4)部署tomcat,进行测试
修改员工的功能实现
逻辑应该经过一个查询组件,进行显示该员工原有的信息,然后在该页面中,进行修改部分值,最后点击提交,保存到数据库
1)编写web.xml,新添加一对配置
<servlet>
<servlet-name>toUpdateEmp</servlet-name>
<servlet-class>com.shuilidianli.employee.web.ToUpdateEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>toUpdateEmp</servlet-name>
<url-pattern>/toUpdate</url-pattern>
</servlet-mapping>
2)编写ToUpdateEmp组件
3)测试
4)编写web.xml,新添加一对配置
<servlet>
<servlet-name>updateEmp</servlet-name>
<servlet-class>com.shuilidianli.employee.web.UpdateEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>updateEmp</servlet-name>
<url-pattern>/updateEmp</url-pattern>
</servlet-mapping>
5)编写对应的UpdateEmp组件
处理请求资源路径
什么是请求资源路径
在浏览器地址栏中输入的地址格式如下:
https://ip:port/appName/xxx.html?.....
http://localhost:8088/day44_servlet/servlet03
处理请求资源路径的过程
当浏览器地址栏上输入https://ip:port/appName/xxx.html时
-
浏览器依据ip和port,与servlet容器建立连接,然后将后面的请求资源路径发送给servlet容器
-
servlet容器依据应用名/appName找到应用所在的文件夹,容器会默认请求的是一个servlet。
-
开始查找web.xml文件中的所有的servlet配置<url-pattern> ,查看是否有匹配的请求资源路径,如果有,就定位到对应的servlet组件
匹配方式以下有三种
1)精确匹配
通过将请求资源路径中的具体资源名称与web.xml文件中的url-pattern进行对比,严格匹配相等后找到对应资源并执行。 如
<url-pattern>/abc.html<url-pattern>
此时,尽管应用中有abc.html这个具体的页面,也会去执行该url-pattern对应的servlet组件,而不是返回这个具体的abc.html
2)通配符匹配
使用“*”号来匹配0个或者多个字符,如下写法
<url-pattern>/*<url-pattern>
代表输入任何不同的url地址都将匹配成功,比如
http://ip:port/appName/abc.html http://ip:port/appName/abc/def/ghi 这些地址都会匹配成功
3)后缀匹配
不能使用斜杠开头,使用*. 开头的任意多个字符,如
<url-pattern>*.do<url-pattern>
会匹配以.do结尾的请求,以下的地址都能匹配成功
http://ip:port/appName/abc.do http://ip:port/appName/abc/def/gh/abc.do
以什么结尾,自行决定,有意义即可。比如
<url-pattern>*.school<url-pattern> <url-pattern>*.company<url-pattern>
4)无匹配的Servlet的处理
如果上述三者匹配都没有匹配成功时,容器就会查找相应的文件
-
查找到对应的文件,则返回
-
找不到对应的文件,返回404
5)三者的优先级
精确匹配> 通配符匹配 > 后缀匹配
6)三种匹配方式的共存问题:
在web.xml文件中可以有精确匹配,也可以有通配符匹配 在web.xml文件中可以有精确匹配,也可以有后缀匹配 在web.xml文件中通配符匹配和后缀匹配可以共存的,但是通配符已经可以拦截所有的后缀匹配了,因此后缀匹配无效。所以写与不写都一样了。
3.4.3 Servlet合并
一般情况下,Servlet的主要作用是充当控制器的角色,即接受请求后,分发给不同的资源,这时Servlet只需要有一个就可以完成分发的过程,所以需要将Servlet合并。
实现合并的步骤如下:
第一步:使用后缀匹配模式,修改web.xml文件
-
将配置的多个相关的Servlet节点删除
-
保留一对servlet、servlet-mapping
-
修改url-pattern节点的内容为: *.do
第二步:获取请求资源路径,分析具体请求资源后,依据分析结果调用不同的分支处理代码
-
调用request.getRequestURI()方法获取请求资源路径
-
分析对应资源后分发
String uri = request.getRequestURI();
if(uri.equals("/appName/list.do")){
//......
}else if(uri.equals("/appName/add.do")){
//....
}else if(...){
//....
}