一.请求转发
request.getRequestDispatcher(String path).forward(request,response);
- 分析请求转发的特点:
- 浏览器地址栏不发生改变,依然是/forward/s1,不是目标地址(/forward/s2).
- 请求转发只发送一个请求.
- 共享同一个请求中的数据.
- 最终响应给浏览器的由Servlet2来决定.
- 请求转发不能跨域访问,只能跳转到当前应用中的资源.
- 请求转发可以访问WEB-INF目录中的资源.
WEB-INF文件中放置的是敏感性的动态资源, 不允许浏览器直接访问, 但是允许通过请求转发间接访问。
Serlvet1
@WebServlet("/forward/s1")
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("before....s1--->" + req);
// 跳转:请求跳转到s2
req.getRequestDispatcher("/forward/s2").forward(req, resp);
// 页面输出
resp.getWriter().write("response--->s1");
System.out.println("after--->s1");
}
}
Serlvet2
@WebServlet("/forward/s2")
public class Servlet2 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println(req + "<-----before...s2");
//页面输出
resp.getWriter().write("response<---s2");
System.out.println("after<---s2");
}
}
- 转发路径
- 如果没以 / 开头,表示相对于 /forward/
- 如果以 / 开头,缺什么补什么
二.URL重定向
response.sendRedirect(String url);
- 分析URL重定向的特点:
- 浏览器地址栏发生改变,从/redirect/s1,变成目标地址(/redirect/s2).
- URL重定向发了两次请求.
- 因为URL重定向是两次独立的请求,所以不共享请求中的数据.
- 最终响应给浏览器的由Servlet2来决定(把目标地址拷贝到浏览器地址栏,敲回车).
- URL重定向能跨域访问,可以访问其他应用中的资源.
- URL重定向不能访问WEB-INF目录中的资源.
Servlet1
//重定向
@WebServlet("/redirect/s1")
public class Servlet1 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("before--->s1");
//重定向到s2
req.getParameter("username");
//getContextPath获取上下文路径
resp.sendRedirect(req.getContextPath() + "/redirect/s2");
resp.getWriter().write("response--->s1");
System.out.println("after--->s1");
}
}
Servlet2
@WebServlet("/redirect/s2")
public class Servlet2 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("before<---s1");
//重定向到s2
req.getParameter("username");
resp.getWriter().write("response<---s2");
System.out.println("after<---s2");
}
}
- 路径
- 响应路径没有以 / 开头,表示相对/redirect的路径
- 以 / 开头,表示缺少上下文路径的上一层路径
三.作用域对象
-
request: 每一次请求都是一个新的request对象,如果在Web组件之间需要共享同一个请求中的数据,只能使用请求转发.
-
session: 每一次会话都是一个新的session对象,如果需要在一次会话中的多个请求之间需要共享数据,只能使用session.
-
application: 应用对象,Tomcat启动到Tomcat关闭,表示一个应用,在一个应用中有且只有一个application对象.作用于整个Web应用,可以实现多次会话之间的数据共享.
-
对象类型
对象名称 对象的类型
request HttpServletRequest
session HttpSession
application(servletContext) ServletContext
- 操作共享数据
- 设置作用域中的共享数据.
作用域对象.setAttribute(String name,Object value); - 获取作用域中的共享数据.
Object value = 作用域对象.getAttribute(String name); - 删除作用域中的指定的共享数据.
作用域对象.removeAttribute(String name);
- 设置作用域中的共享数据.
注意:在哪一个作用域中设置共享数据,就只能从该作用域中取出数据.
三.计数器案例
获取ServletContext三种方式
ServletContext context1 = super.getServletContext();
ServletContext context2 = req.getSession().getServletContext();
ServletContext countext3 = req.getServletContext();
请求页ScopeServlet
// 计数器
@WebServlet("/scope")
public class ScopeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// HttpServletRequest
Integer count_req = (Integer) req.getAttribute("COUNT_IN_REQUEST");
if (count_req == null) {// 不存在
req.setAttribute("COUNT_IN_REQUEST", 1);
} else {// 加1放回
req.setAttribute("COUNT_IN_REQUEST", count_req+1);
}
// Session
HttpSession session = req.getSession();
Integer count_session = (Integer) session.getAttribute("COUNT_IN_SESSION");
if (count_session == null) {
session.setAttribute("COUNT_IN_SESSION", 1);
} else {
session.setAttribute("COUNT_IN_SESSION", count_session + 1);
}
// 全局变量
ServletContext app = req.getServletContext();
Integer count_app = (Integer) app.getAttribute("COUNT_IN_APP");
if (count_app == null) {
app.setAttribute("COUNT_IN_APP", 1);
} else {
app.setAttribute("COUNT_IN_APP", count_app + 1);
}
req.getRequestDispatcher("/result").forward(req,resp);
}
}
响应页ResultServlet
@WebServlet("/result")
public class ResultServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
Integer count_request = (Integer)req.getAttribute("COUNT_IN_REQUEST");
PrintWriter writer = resp.getWriter();
writer.write("request--->" + count_request);
writer.write("<br>");
Integer count_session = (Integer)req.getSession().getAttribute("COUNT_IN_SESSION");
writer.write("session--->" + count_session);
writer.write("<br>");
Integer count_app = (Integer)req.getServletContext().getAttribute("COUNT_IN_APP");
writer.write("app--->" + count_app);
writer.write("<br>");
}
}
四.JSP语法
- JSP的注释:
- 作用:注释Java脚本代码
- 语法:<%–这是JSP注释–%>
- JSP中的Java脚本片段:(实际开发中,应做到JSP中不能出现一行Java脚本片段)
- 作用:书写Java代码逻辑
- 语法: <% 语句1; 语句2; %>
- 原理:其中的语句会原封不动的被服务器翻译到对应的Servlet的_jspService方法中。
- JSP的Java脚本表达式:
- 作用:输出数据到页面上
- 语法:<%=表达式%>(实际上就是调用输出流打印到页面上) out.print(表达式);
- JSP的声明:
- 作用:定义类的成员
- 语法:<%! Java代码 %>
- 原理:其中的语句会原封不动的被服务器翻译到对应Servlet类中,作为成员变量和方法.
五.静态和动态包含
- 静态包含:使用JSP的include指令:
<%@include file="被包含的页面文件" %>
特点:
在翻译阶段就已经把多个JSP,合并在一起.
- 动态包含:使用JSP的动作指令.
<jsp:include page="被包含的页面文件"/>
特点:
把每一个JSP都翻译成Servlet类,在运行时期,动态的合并在一起.
六.综合案例
运用到之前写的DAO重构
请求StudentServlet
WebServlet("/stu")
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private IUserDAO<User> iuser = new UserDAOImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
// 1)获取参数
// 2)调用业务方法处理
List<User> list = iuser.queryAll();
// 设置共享参数
req.setAttribute("userList", list);
// 3)控制页面请求
req.getRequestDispatcher("/WEB-INF/views/user/list.jsp").forward(req, resp);;
/*req.getRequestDispatcher("/WEB-INF/hello.html").forward(req, resp);*/
}
}
list.jsp
<%@page import="com.dusk.smis.domain.User"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>学生列表</title>
</head>
<body>
<h1>学生信息表</h1>
<%
List<User> list = (List<User>) request.getAttribute(("userList"));
%>
<table border='1' cellpadding="0" cellspacing="0" width="80%" >
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>操作</th>
</tr>
<%
for (User user : list) {
%>
<tr>
<td><%=user.getId()%></td>
<td><%=user.getUsername()%></td>
<td><%=user.getScore()%></td>
<td>删除 | 编辑</td>
</tr>
<%
}
%>
</table>
</body>
</html>