1995年java诞生,没有jsp,只有Servlet,
Servlet开发:Servlet上嵌套html代码,非常繁琐。
1998年,出现jsp,方便写html代码,并且可以在html代码中嵌套java代码,把所有逻辑都写在jsp上,也非常繁琐。
所以,最好的方式,就是用jsp完成html,js,css代码;用Servlet完成java代码。
jsp本质,就是Servlet。
1 jsp脚本
1)<%java代码%> ----- 内部的java代码翻译到service方法的内部,所以这里不能写方法
2)<%=java变量或表达式> ----- 会被翻译成service方法内部out.print()
3)<%!java代码%> ---- 会被翻译成servlet的成员的内容,这里可以写方法
例:
test.jsp:
<% int i=0; System.out.println(i); %> <%=i+"..." %> <%!String str="Hello"; %> <%=str %>
2 jsp运行原理
jsp本质,就是Servlet。
访问上面的text.jsp后,在这个目录中可以看到,生成了java文件和class文件
打开java文件,可以看到这个类继承HttpJspBase
看一下HttpJspBase的继承树:
在eclipse中:
(也可以Ctrl+Shift+T,如果打不开,就加载一下源码apache-tomcat-7.0.52-src.zip)
可以看到,这里继承了HttpServlet
jsp在第一次被访问时会被Web容器翻译成servlet,再执行。
看一下上面写的代码在test_jsp.java中的位置
3 jsp注释
1)Html注释:<!--注释内容--> ---可见范围 jsp源码、翻译后的servlet、页面显示html源码
2)java注释://单行注释 /*多行注释*/ --可见范围 jsp源码 翻译后的servlet
3)jsp注释:<%--注释内容--%> ----- 可见范围 jsp源码可见
所以jsp注释最安全,可以项目成员之间看
Html注释可以给用户看
4 jsp指令
jsp的指令是指导jsp翻译和运行的命令,jsp包括三大指令
4.1 page指令
格式:<%@ page 属性名1= "属性值1" 属性名2= "属性值2" ...%>
常用属性:
language:jsp脚本中可以嵌入的语言种类
contentType:解决响应的中文乱码:response.setContentType(text/html;charset=UTF-8)
pageEncoding:当前jsp文件的本身编码,内部可以包含contentType
session:是否jsp在翻译时自动创建session,默认true
import:导入java的包
errorPage:当当前页面出错后跳转到哪个页面
isErrorPage:当前页面是一个处理错误的页面
Tips:
可以配一个全局的错误页面:
4.2 include指令
页面包含(静态包含)指令,可以将一个jsp页面包含到另一个jsp页面中
格式:<%@ include file="被包含的文件地址"%>
例:
header.jsp:写个导航内容
body.jsp:
<%@ include file="/header.jsp" %> <p>这是正文</p>
4.3 taglib指令
在jsp页面中引入标签库(jstl标签库、struts2标签库)
格式:<%@ taglib uri="标签库地址" prefix="前缀"%>
5 jsp内置/隐式对象
jsp被翻译成servlet之后,service方法中有9个对象定义并初始化完毕,在jsp脚本中可以直接使用这9个对象
名称 |
类型 |
描述 |
out |
javax.servlet.jsp.JspWriter |
用于页面输出 |
request |
javax.servlet.http.HttpServletRequest |
得到用户请求信息, |
response |
javax.servlet.http.HttpServletResponse |
服务器向客户端的回应信息 |
config |
javax.servlet.ServletConfig |
服务器配置,可以取得初始化参数 |
session |
javax.servlet.http.HttpSession |
用来保存用户的信息 |
application |
javax.servlet.ServletContext |
所有用户的共享信息 |
page |
java.lang.Object |
指当前页面转换后的Servlet类的实例(相当于在普通类中的this) |
pageContext |
javax.servlet.jsp.PageContext |
JSP的页面容器 |
exception |
java.lang.Throwable |
表示JSP页面所发生的异常,在错误页中才起作用 (配置了isErrorPage="true"的页面) |
5.1 out对象
out的类型:JspWriter
out作用就是向客户端输出内容----out.write()
和response.getWriter().write的区别
例:out.jsp
aaaaaaaaaaaaa <%out.write("bbbbbbbbbb"); response.getWriter().write("cccccccccc"); %> <%="dddddddddddd" %>
打开out_jsp.java:
out缓冲区的内容会写到respons缓冲区,所以结果是c,a,b,d
out缓冲区默认8kb,可以设置成0(一般不设置),代表关闭out缓冲区(out对象还存在),内容直接写到respons缓冲器
5.2 pageContext对象
1)jsp页面的上下文对象
pageContext是一个域对象,三个方法:
setAttribute(String name,Object obj)
getAttribute(String name)
removeAttrbute(String name)
2)作用范围:本jsp页面
例:page1:
<% //pageContext域设置值 pageContext.setAttribute("name", "zhangsan"); %> <% //pageContext域取值 String name=(String)pageContext.getAttribute("name"); out.write("page1中name的值是"+name); %>
page2:
<% String name=(String)pageContext.getAttribute("name"); out.write("page2中name的值是"+name); %>
3)pageContext可以向指定的其他域中存取数据(后面学的EL 表达式的底层代码)
setAttribute(String name,Object obj,int scope)
getAttribute(String name,int scope)
removeAttrbute(String name,int scope)
findAttribute(String name)
4)findAttribute方法:如果四个域中的key值都相同,默认从小的域开始找,找到value,就不再往下找了,
pageContext域 < request域 < session域 < application域
例:
<% request.setAttribute("name", "zhangsan"); pageContext.setAttribute("name", "lisi", pageContext.SESSION_SCOPE); pageContext.setAttribute("name", "wangwu",pageContext.APPLICATION_SCOPE); %> <%=request.getAttribute("name") %> <%=pageContext.getAttribute("name",pageContext.SESSION_SCOPE) %> <%=pageContext.getAttribute("name",pageContext.APPLICATION_SCOPE) %>
再加上:
<hr> <%=pageContext.findAttribute("name") %>
Tisp:
1. page对象与pageContext对象不是一回事
2. 四大作用域的总结
pageContext域:当前jsp页面范围
request域:一次请求
session域:一次会话
application域:整个web应用
3.jsp有四个域对象,servlet有三个域对象
5)可以获得其他8大隐式对象(用的较少)
例如: pageContext.getRequest()
pageContext.getSession()
6 jsp标签
6.1页面包含(动态包含)
例:jspHeader.jsp:写上导航内容
jspBody.jsp:
<jsp:include page="/jspHeader.jsp"></jsp:include>
<hr>
这是正文
与静态包含的区别:
效果上一样,所以用哪个都可以。
本质上:
静态:jspHeader.jsp没有被翻译成servlet
动态:把jspHeader.jsp也被翻译成servlet了
6.2请求转发
(一般不用,还是用servlet请求转发)
<jsp:forward page="要转发的资源" />
例:
<!-- 请求转发 --> <jsp:forward page="/page2.jsp"></jsp:forward>
7练习:页面显示商品列表
ProductListServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Product> list=productService.getAllProduct(); request.setAttribute("ProductList", list); //存入集合 request.getRequestDispatcher("/product_list.jsp").forward(request, response); //请求转发 }
Header.jsp中:
<a href="/20190111Shopping/ProductListServlet">手机数码</a>
product_list.jsp中写一个for循环:
<% List<Product> list=(List)request.getAttribute("ProductList"); for(Product product:list){ out.write("<div class='col-md-2'>"); out.write("<a href='product_info.htm'> <img src='"+product.getPimage()+"' width='170' height='170' style='display: inline-block;'></a>"); out.write("<p><a href='product_info.html' style='color: green'>"+product.getPname()+"</a></p>"); out.write("<p><font color='#FF0000'>商城价:¥"+product.getMarket_price()+"</font></p></div></div>"); } %>
注意字符串拼接的技巧
访问http://localhost:8080/20190111Shopping/index.jsp,
点击手机数码: