Servlet跟JSP中转发与重定向的区别&动态include和静态include的区别
Servlet中转发与重定向的区别
转发和重定向都能让浏览器获得另外一个URL所指向的资源,但两者的内部运行机制有着很大的区别。
1、转发:有两种方式获得转发对象(RequestDispatcher):一种是通过HttpServletRequest的getRequestDispatcher()方法获得,一种是通过ServletContext的getRequestDispatcher()方法获得;
以前的request范围中存放的变量不会失效,就像把两个页面拼到了一起。 例如:
RequestDispatcher rd = request.getRequestDispatcher("forwaordResult.jsp");//转发到forwaordResult.jsp页面
rd.forward(request, response);
详解:假设浏览器访问servlet1,而servlet1想让servlet2为客户端服务。此时servlet1调用forward()方法,将请求转发给servlet2。但是调用forward()方法,对于浏览器来说是透明的,浏览器并不知道为其服务的Servlet已经换成Servlet2,它只知道发出了一个请求,获得了一个响应。浏览器URL的地址栏不变。
在JSP中转发的表现形式是:
<jsp:forward page="forwardResult.jsp">
2、重定向:HttpServletResponse的sendRedirect()方法。
服务器根据此请求寻找资源并发送给客户,它可以重定向到任意URL,不能共享request范围内的数据。例如:response.sendRedirect(“forwaordResult.jsp");//重定向到forwaordResult.jsp
详解:假设浏览器访问servlet1,而servlet1想让servlet2为客户端服务。此时servlet1调用sendRedirect()方法,将客户端的请求重新定向到Servlet2。接着浏览器访问servlet2,servlet2对客户端请求作出反应。浏览器URL的地址栏改变。
3、主要区别:
(1)sendRedirect()方法不但可以在位于同一个主机上的不同Web应用程序之间进行重定向,而且可以将客户端重定向到其他服务器上的Web应用程序资源。而forward()方法只能将请求转发给同一Web应用的组件。
(2)forward是在服务器端的跳转,就是客户端一个请求发给服务器,服务器直接将请求相关的参数的信息原封不动的传递到该服务器的其他jsp或servlet去处理,而sendredirect是在客户端的跳转,
(3)转发:浏览器URL的地址栏不变。
重定向:浏览器URL的地址栏改变。
动态include和静态include的区别
JSP中所谓静态include的表现形式:
<%@ include file="headerStatic.jsp" %>
<%@ include file="mainStatic.jsp" %>
<%@ include file="footerStatic.jsp" %>
JSP中所谓动态include的表现形式:
<jsp:include page="header.jsp"/>
<jsp:include page="main.jsp"/>
<jsp:include page="footer.jsp"/>
然后来看servlet中所谓include的表现形式
RequestDispatcher rd; rd = request.getRequestDispatcher("/header.jsp"); rd.include(request, response); rd = request.getRequestDispatcher("/main.jsp"); rd.include(request, response); rd = request.getRequestDispatcher("/footer.jsp"); rd.include(request, response);
现在来真正分析一下JSP动态include和静态unclude的区别:
在静态JSP生成的servlet文件中看到如下关键代码
static { _jspx_dependants = new java.util.ArrayList(3); _jspx_dependants.add("/headerStatic.jsp"); _jspx_dependants.add("/mainStatic.jsp"); _jspx_dependants.add("/footerStatic.jsp"); }
使用的是静态代码块来实现,也就是说类加载的时候把三个文件读进来
反观动态include:是通过这样三句代码
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "header.jsp", out, false); org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "main.jsp", out, false); org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "footer.jsp", out, false);
注意一下动静态我用的文件名不一样,静态的加了static。
然后我们来看一下tomcat的tomcat\work\Catalina\localhost\WebTest\org\apache\jsp这个文件夹,也就是编译成servlet的文件夹
这里面并没有编译出headerStatic文件
也就是说
jsp:include是先编译一下included.jsp文件,然后再包含 先编译,后包含 编译成多个文件
@ include是先把文件包含就来,然后统一编译 先包含,后编译 编译成一个文件
那么既然静态inlcude是在静态代码块中实现的,那么服务器不重启的话,类就已经加载在内存,如果修改herder.jsp,主页面应该是不会变化的。
但我做了个简单的测试,我把header.jsp和headerStatic.jsp文件的css样式改了,结果我发现刷新页面动静态都改变了
试验到这里,我发现我肯定理解错网上那些面试题中的答案了
经过更复杂的试验,个人得出这样的结论
- @ include子页面拿不到request中的数据
- @ include如果涉及到数据库,它只加载一次,当数据库的值变化时,子页面的数据不变化,也就是说静态include最好包含的是静态页面
最后想说我总结的比一定准,不准之处请指教吧。