请求转发和重定向
request除了可以作为请求对象之外,还可以作为域对象,但是该域对象的取值范围,是一次请求范围之内(浏览器地址栏没有发生跳转访问别的资源)
作用:将servlet中的数据通过request对象带到jsp页面;
请求转发
-
通过请求对象获取请求转发对象
RequestDispatcher requestDispatcher = req.getRequestDispatcher("资源相对路径");
-
定位具体资源
requestDispatcher.forward(req,resp);
实现内部资源的跳转:通过浏览器发起访问,工程中的资源会从一个地址跳转到另外一个地址,但浏览器端的地址不会发生改变。
请求对象req还可以作为与对象存放数据,因为请求转发方式是不会发生地址的跳转的,所以在req的作用范围(一次请求范围)之内,因此可以在跳转的资源中获取到存放的数据。
@WebServlet("/hello01")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//往域中存放数据
req.setAttribute("username","jack");
req.setAttribute("password","123456");
//获取请求转发对象 参数是另一个资源的相对路径
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/hello02");
//调用forward 定位具体资源
requestDispatcher.forward(req,resp);
}
}
@WebServlet("/hello02")
public class HelloServlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//取出域中的数据
Object username = req.getAttribute("username");
Object password = req.getAttribute("password");
System.out.println(username);
System.out.println(password);
}
}
输出结果:
jack
123456
在访问这个地址后,地址栏的地址没有发生跳转,但是访问的资源已经到了/hello02,通过后端控制台打印就可看到获取到了数据。
请求重定向
可以完成内部资源的跳转,而且浏览器的地址是会发生改变的,这种情况下,不能取到request域中的数据
hello03后端资源:
@WebServlet("/hello03")
public class HelloServlet03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//往域中存放数据
req.setAttribute("key","value");
//请求重定向 是响应对象
//参数是绝对路径
resp.sendRedirect("http://localhost:8080/servlet/hello04");
}
}
hello04后端资源:
@WebServlet("/hello04")
public class HelloServlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//取出数据
Object key = req.getAttribute("key");
System.out.println("----"+key+"----");
}
}
-
通过浏览器方法hello03资源
-
浏览器端地址跳转
-
控制台打印key值
因为发生了重定向是要发生地址跳转的,超出了req与对象的作用范围(一次请求)内,所以在hello04资源中是获取不到hello03资源的req的数据的。
请求重定向到静态html页面
hello05:
@WebServlet("/hello05")
public class HelloServlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*//获取转发对象 相对路径 前端资源/代表web文件夹下
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/html/test.html");
//定位到具体资源
requestDispatcher.forward(req,resp);*/
//请求重定向
resp.sendRedirect("http://localhost:8080/servlet/html/test.html");
}
}
test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
成功访问了前端静态资源
</body>
</html>
浏览器访问结果:
总结:
存放在ServletContext域对象中的数据,不管是通过重定向还是请求转发都是可以在跳转的资源中的获取到的。
存放在请求域对象request中的数据,如果是通过请求转发,没有地址的跳转,是可以在另一资源中获取到的;相反,若干是重定向,有地址的跳转,那么不可以在另一个资源中获取到访问资源request中存放的数据。
JSP模板引擎
html是前端中静态的资源,是不能直接获取到后端的资源的。jsp模板引擎,可以动态渲染后端数据到前端,jsp中的el表达式可以取出后端域中的数据。
格式:
${域对象的key}
@WebServlet("/hello06")
public class HelloServlet06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user1=new User("jack1","132");
User user2=new User("jack2","132");
User user3=new User("jack3","132");
ArrayList<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
//获取ServletContext域对象
ServletContext servletContext = getServletContext();
servletContext.setAttribute("users",users);
//重定向
resp.sendRedirect("http://localhost:8080/servlet/jsp/test.jsp");
}
}
test.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body> ${users}</body></html>
浏览器访问结果:
重定向有地址的跳转
JSP
JSP(全称JavaServer Pages)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。
JSP是一个前端的模板引擎,用于渲染后端数据,底层本质是一个Servlet程序。JSP可以动态的获取到后端的数据,由于底层是servlet,servlet底层是java,所以可以在代码脚本中去编写java代码
EL表达式
可以在后端资源中的域对象ServletContext中设置属性,然后在跳转的JSP文件中通过EL表达式获取到属性值。可以用request请求域对象和ServletContext域对象来设置属性和值,这基于方式是请求转发方式还是请求重定向方式,如果是请求转发方式,那么可以用request请求域对象或者ServletContext域对象来setAttribute,因为请求转发方式不会发生地址的跳转,request请求域对象也可以进行传递值;如果是重定向方式,那么就只能用ServletContext域对象来setAttribute,因为其作用范围广,地址跳转,仍然能够存取数据;
1、重定向方式
case2Servlet
@WebServlet("/case2Servlet")public class case2Servlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); ArrayList<User> users = Jdbc.selectDB(); //采用重定向方式 ServletContext servletContext = getServletContext(); servletContext.setAttribute("users",users); resp.sendRedirect("http://localhost:8080/servlet/jsp/case2Jsp01.jsp"); }}
case2Jsp01.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body> ${users}</body></html>
浏览器访问:
2、请求转发方式
JSP脚本
- 声明脚本的格式:<%!声明java代码%>
- 表达式脚本的格式:<%=表达式%>
- 代码脚本的格式:<%java语句%>
<%@ page import="java.util.ArrayList" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><%--jsp代码脚本--%><% String name="Tom"; Integer age=50; Object o=new Object(); System.out.println(name+" "+age+" "+o); for (int i=0;i<10;i++) System.out.println(i); ArrayList<Object> objects = new ArrayList<>();//会自动导包 ArrayList<User> users = new ArrayList<>(); users.add(new User(12,"jack1","123456")); users.add(new User(12,"jack2","123456")); users.add(new User(12,"jack3","123456")); users.add(new User(12,"jack4","123456"));%><%--声明脚本--%><%! private Integer i=5;%><html><head> <title>test</title></head><body> <%--表达式脚本--%> <%=age%> <%=name%> <%=users.get(0).getUsername()%></body></html>
JSP九大内置对象:
JSP程序在执行的时候,底层会生成对应的源代码和字节码文件,在源代码中,会封装9大内置对象,包括字符流对象、异常对象、域对象
- request
- response
- pageContext
- exception
- application
- out
- page
- session
- servletConfig
JSP四大域对象:
域对象是都可以存取值的
-
pageContext
JSP内置的文本域对象,取值范围是当前的JSP页面,出了该页面的数据就无法访问
-
request
是一个请求域对象,取值范围是一次请求范围之类,浏览器只要地址不发生改变,则可以访问到数据
-
session
是一个会话域对象,取值范围是浏览器的开启到关闭,对应的生命周期也是浏览器的开启到关闭
-
application
实际上就是一个ServletContext对象,取值范围是整个web工程
下面根据代码的栗子来说明不同的取值范围:
- 首先在test04.jsp文件 JSP代码脚本各种域对象存放数据,然后在body部分进行取出数据
test04.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--声明一个jsp脚本--%><% //存放数据到域中 request.setAttribute("key1","value1"); request.setAttribute("key2","value2"); request.setAttribute("key3","value3"); pageContext.setAttribute("pageContext","pageContext"); request.setAttribute("request","request"); session.setAttribute("session","session"); application.setAttribute("application","application");%><html><head> <title>test</title></head><body> <%--用表达式脚本取出域中的数据--%> <%=request.getAttribute("key1")%><br> <%=request.getAttribute("key2")%><br> <%=request.getAttribute("key3")%><br> pageContext的value值为:<%=pageContext.getAttribute("pageContext")%><br> request的value值为:<%=request.getAttribute("request")%><br> session的value值为:<%=session.getAttribute("session")%><br> application的value值为:<%=application.getAttribute("application")%><br></body></html>
- 浏览器端
? 可以看到4个域对象现在都能访问到其中存取的数据
- 在同一工程下新建一个test05.jsp,用于取出域对象中的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>test</title></head><body> pageContext的value值为:<%=request.getAttribute("pageContext")%><br> request的value值为:<%=request.getAttribute("request")%><br> session的value值为:<%=session.getAttribute("session")%><br> application的value值为:<%=application.getAttribute("application")%><br></body></html>
- 浏览器端访问
? 可以发现pageContext和request域对象的值已经获取不到了,因为pageContext的取值范围是当前JSP文件,request的取值范围是一次请求范围之内。访问的JSP文件改变,访问地址改变,明显超出了这两者的取值范围。
-
关闭浏览器,重新打开浏览器,再次访问test05.jsp页面
可以发现session域对象的值也获取不到了,因为session域对象的取值范围是浏览器的开启到关闭。而application是一直可以获取到的,因为它的取值范围是整个web工程,只要web工程运行,就可以随时在任何地方都能访问到值。