一、什么是jsp
jsp的全称是Java Server page(Java的服务器界面)它将java和html相结合
jsp的主要作用是代替Servlet程序回传html页面的数据。
因为Servlet程序回传html页面数据是一件非常繁琐的事情,开发成本和维护成本都极高。
<!--jsp依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/tomcat/jasper-runtime -->
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
</dependency>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<!DOCTYPE html>");
writer.write("<html lang=\"en\">");
writer.write("<head>");
writer.write("<meta charset=\"UTF-8\">");
writer.write("<title>Title</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("<h1>test</h1>");
writer.write("</body>");
writer.write("</html>");
}
jsp本质上是一个servlet。
当我们第一次访问jsp页面的时候,Tomcat服务器会帮我们把jsp页面翻译成一个Java源文件。并且对它进行编译成为.class字节码程序。
打开jsp翻译后的Java文件:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.59
* Generated at: 2021-09-02 20:01:50 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class a_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(" <h1>这是jsp页面</h1>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
接下来我们修改index.jsp的内容,定义一个java变量,并取出输出到页面:
<body>
<%
String name = "zhangsan";
%>
<%=name%>
</body>
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
String name = "zhangsan";
out.write('\r');
out.write('\n');
out.print(name);
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
观察翻译出来的源代码不难发现,其底层实现也是通过输出流把页面数据回传给客户端。所以jsp其实还是一个servlet,只不过它代替了人们以前在servlet中拼接html代码的工作,使得在开发中jsp只用专注于html代码的编写,由于html代码和java代码分离,也使维护起来更省力。
jsp的执行过程
•客户端发出Request (请求);
•tomcat 容器将JSP 转译成Servlet 的源代码;
•将产生的Servlet 的源代码经过编译后,并加载到内存执行;
•进入Servlet的执行过程;
二、jsp指令元素
指令(Directives)主要用来提供整个JSP 网页相关的信息,并且用来设定JSP网页的相关属性,例如:网页的编码方式、语法、信息等。
–起始符号为: <%@
–终止符号为: %>
–中间部分就是一些指令和一连串的属性设定,如下所示:
–<%@ directive attribute =“value” %>
jsp页面包含三种指令:
–page指令
–include指令
–taglib指令
1、page指令
page指令可以修改jsp页面的一些重要属性
(1)language属性:
表示jsp翻译后是什么语言文件。目前只支持java
(2)contentType属性:
表示jsp返回的数据类型是什么,也是源码中response.setContentType()的参数值
(3)import属性:
用于导包和导类
(4)errorPage:错误后自动跳转到的路径
errorPage="/error500.jsp"
2、include指令
3、taglib指令
三、jsp中的常用脚本
1、声明脚本:<%! 声明Java代码%>(全局)
(1)声明类属性
(2)声明静态代码块
(3)声明类方法
(4)声明内部类
2、(常用)表达式脚本<%=表达式%>
在jsp页面上输出数据
表达式脚本都会被翻译成out.print(),输出到页面上
表达式脚本中的表达式不能以分号结束
3、代码脚本<% Java代码 %>
动态路径:
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
四、jsp的注释
1、html注释:
html注释会被翻译到Java源代码中。以out.write输出到客户端
2、Java注释:
单行注释://
多行注释:/**/
Java注释会被翻译到Java源代码中
3、jsp注释:
<%-- -->
jsp注释,可以注释掉jsp页面中的所有代码
五、jsp中的九大内置对象
jsp内建对象是: 在jsp中预定义好的对象;开发者可以在jsp直接使用,无需定义和创建。
–page
–out
–request
–response
–session
–application
–config
–exception
pageContext
四个作用域对象:
scope.jsp:
scope2.jsp:
scope.jsp中加上跳转语句
直接跳转:pageContext为null
直接在浏览器输入scope2:request为null
关闭浏览器再访问scope2:session为null
重启tomcat再访问scope2:application为null
使用的优先级顺序
六、jsp动作元素(action)
•动作元素实际就是jsp页面的一些标记,通过解释转换成相应的java代码,达到某些功能。
•动作元素与指令元素不同,动作元素是在客户端请求时动态执行的,每次有客户端请求时可能都会被执行一次,而指令元素是在编译时被编译执行,它只会被编译一次。
•一个JSP动作元素,通过它可以操作隐含对象和其它服务器端对象,也能够定义新的脚本变量。
•动作元素(Actions)遵循XML的语法,由一个开始标记开始,一个主体和一个结束标记。如果主体是空的,它也可以使用空标记。标记必须有一个前缀 ”jsp:”。
<jsp:include page=“userinfo.jsp”>
<jsp:param name=“username” value=“hellking”>
….
</jsp:include>
<jsp:forward page=“userinfo.jsp”>
<jsp:param name=“username” value=“hellking”>
…
</jsp:forward>
<jsp:plugin type=“applet” code=“com.imageapplet”>
<jsp:param name=“username” value=“hellking”>
</jsp:plugin>
//一个javaBean
public class LoginInfoBean {
private String suser = "";
private String spwd = "";
public String getSpwd() {
return spwd;
}
public void setSpwd(String spwd) {
this.spwd = spwd;
}
public String getSuser() {
return suser;
}
public void setSuser(String suser) {
this.suser = suser;
}
}
<jsp:useBean id=“login" class="LoginInfoBean"/>
//上面的动作元素相当于下面的java代码;即jsp转化为servlet时也会被转换成类似下面的代码;
<%
LoginInfoBean login =null;
login =request.getAttribute("login");
if(login ==null){
login =new LoginInfoBean();
request.setAttribute("login", login);
}
%>
//useBean作用: a)在jsp页面中定义变量; b)查找作用域中的数据对象;如找到赋给jsp中的变量;如没找到创建并放到作用域中
JSP技术提供了三个关于JavaBean组件的动作元素,即JSP标签,它们分别为:
<jsp:useBean >标签:用于在JSP页面中查找或实例化一个JavaBean组件。
<jsp:setProperty >标签:用于在JSP页面中设置一个JavaBean组件的属性。
<jsp:getProperty >标签:用于在JSP页面中获取一个JavaBean组件的属性。
"id"属性用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。
"class"属性用于指定JavaBean的完整类名(即必须带有包名)。
"scope"属性用于指定JavaBean实例对象所存储的域范围,其取值只能是page、request、session和application等四个值中的一个,其默认值是page。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="person" class="com.demo.person.Person" />
<jsp:setProperty name="person" property="name" value="ForMe" />
<jsp:setProperty name="person" property="age" value="20"/>
<jsp:setProperty name="person" property="password" value="113456"/>
<jsp:setProperty name="person" property="sex" value="male"/>
<html>
<head>
<title>jspTest1</title>
</head>
<body>
<jsp:getProperty property="name" name="person"/><br>
<jsp:getProperty property="password" name="person"/><br>
<jsp:getProperty name="person" property="age"/><br>
<jsp:getProperty name="person" property="sex"/><br>
<hr>
<%=person.getName()%><br>
<%=person.getPassword()%><br>
<%=person.getAge()%><br>
<%=person.getSex()%><br>
<hr>
</body>
</html>
项目路径:
<%
String path = request.getContextPath();
String basePath = request.getScheme()+“😕/”+request.getServerName()+“:”+request.getServerPort()+path+“/”;
%>
课堂练习:
在jsp页面中输出99乘法表:
输出10个学生信息到table
请求转发:通过request域回传给jsp
七、EL表达式
1、什么是EL表达式
EL表达式的全称是:Expression Language。是表达式语言。
作用:
EL表达式的主要作用是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出。因为EL表达式在输出数据的时候要比jsp的表达式脚本简洁很多。
格式:
${表达式}
<body>
<%
request.setAttribute("key","值");
%>
表达式脚本输出的key的值是:<%=request.getAttribute("key")%><br/>
EL表达式输出的key的值是:${key}
</body>
//如果值不存在,表达式脚本输出null,EL表达式不输出内容
<body>
<%
request.setAttribute("key","值");
%>
表达式脚本输出的key的值是:<%=request.getAttribute("key1")%><br/>
EL表达式输出的key的值是:${key1}
</body>
<%=request.getAttribute("key1")==null?"":request.getAttribute("key1")%>
2、EL表达式搜索四个域的顺序
当四个域中都有相同的key数据的时候,EL表达式会按照四个域从小到大的顺序进行搜索,找到就输出。
<body>
<%
//往四个域中都保存了相同的key数据
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
key的值:${key}
</body>
3、EL表达式中输出Bean的普通属性,数组属性,集合属性和map属性
JavaBean:
package com.cykj.web.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Person {
private String name;
private String[] phones;
private List<String> cities;
private Map<String,Object> map;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getPhones() {
return phones;
}
public void setPhones(String[] phones) {
this.phones = phones;
}
public List<String> getCities() {
return cities;
}
public void setCities(List<String> cities) {
this.cities = cities;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
@Override
public String toString() {
return "Person{" +
"name=" + name +
", phones=" + Arrays.toString(phones) +
", cities=" + cities +
", map=" + map +
'}';
}
public Person() {
}
public Person(String name, String[] phones, List<String> cities, Map<String, Object> map) {
this.name = name;
this.phones = phones;
this.cities = cities;
this.map = map;
}
}
jsp:
<body>
<%
Person p = new Person();
p.setName("张三");
p.setPhones(new String[]{"123","234"});
List<String> cityes = new ArrayList<String>();
cityes.add("beijing");
cityes.add("sh");
cityes.add("gz");
p.setCities(cityes);
Map<String,Object> map = new HashMap<String,Object>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
p.setMap(map);
pageContext.setAttribute("person",p);
%>
person:${person}<br/>
person的name属性:${person.name}<br/>
person的数组:${person.phones}<br/>
person的集合:${person.cities}<br/>
person的集合中的个别元素:${person.cities[0]}<br/>
person的Map:${person.map}<br/>
person的Map中的某个Key:${person.map.key1}<br/>
</body>
EL表达式找的不是属性,而是get方法对应的内容(举例)
4、EL表达式运算
(1)关系运算:返回一个布尔值
==或eq:等于 !=或ne:不等于 <或lt:小于 >或gt:大于 <=或le:小于等于 >=或ge:大于等于
(2)逻辑运算
&&或and:与运算
||或or:或运算
!或not:非运算
(3)算术运算
+:加法
-:减法
*:乘法
/或div:除法
%或mod:取余
(4)empty运算
empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false
(5)三元运算
${gender eq 0?"男":"女"}
5、EL表达式中的11个隐含对象
(1)EL表达式获取四个特定域中的属性
(2)pageContext
(3)param,paramValues 获取请求参数的值
(4)header,headerValues获取请求头
(5)cookie
(6)initParam
二、JSTL标签库
<!--JSTL表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库依赖-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
1、引入标签库
2、标签库的使用步骤
(1)导入jar包
(2)引入标签库
3、常用的JSTL标签
(1)<c:set/>标签:可以往域中保存数据
<c:set scope="request" value="张三" var="name"></c:set>
${requestScope.name}
(2)<c:if>标签:用来做if判断
没有else,只能写多个if
<c:if test="${12==12}">
<h1>12等于12</h1>
</c:if>
<c:if test="${12!=12}">
<h1>12不等于12</h1>
</c:if>
(3)<c:choose>标签:多路判断选择标签,类似switch case default
<c:set scope="request" var="score" value="85"></c:set>
<c:choose>
<c:when test="${requestScope.score<60}">
<h1>不及格</h1>
</c:when>
<c:when test="${requestScope.score<75}">
<h1>及格</h1>
</c:when>
<c:when test="${requestScope.score<85}">
<h1>良好</h1>
</c:when>
<c:otherwise>
<h1>优秀</h1>
</c:otherwise>
</c:choose>
注意:
1、标签里面不能使用html注释,要使用jsp注释
2、when标签的父标签一定要是choose标签
(4)<c:forEach>标签:遍历输出
begin:开始的索引
end:结束的索引
var:变量名称
遍历1-10
<c:forEach begin="1" end="10" var="i">
<button>${i}</button>
</c:forEach>
遍历Object类型的数组
items:表示遍历的数据源(数组)
var:表示当前遍历到的数据
<%
request.setAttribute("arr",new String[]{"a","b","c","d"});
%>
<c:forEach items="${requestScope.arr}" var="item">
<h1>${item}</h1>
</c:forEach>
遍历Map
<%
Map<String,String> map = new HashMap<String,String>();
map.put("k1","v1");
map.put("k2","v2");
map.put("k3","v3");
map.put("k4","v4");
request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="entry">
<h1>${entry.key}=${entry.value}</h1>
</c:forEach>
遍历List集合
<%
List<Tbluserinfo> list = new ArrayList<Tbluserinfo>();
for(int i=0;i<10;i++){
Tbluserinfo tbluserinfo = new Tbluserinfo();
tbluserinfo.setMoney(10000);
tbluserinfo.setPhone("13588888888");
tbluserinfo.setRid(i);
tbluserinfo.setUname("tbl"+i);
tbluserinfo.setUpwd("123456");
tbluserinfo.setUsersid(i);
list.add(tbluserinfo);
}
request.setAttribute("list",list);
%>
<table border="1" width="800px" align="center" style="border-collapse:collapse">
<tr>
<th>sid</th>
<th>rid</th>
<th>name</th>
<th>pwd</th>
<th>money</th>
<th>phone</th>
</tr>
<c:forEach items="${requestScope.list}" var="tbl">
<tr>
<td>${tbl.usersid}</td>
<td>${tbl.rid}</td>
<td>${tbl.uname}</td>
<td>${tbl.upwd}</td>
<td>${tbl.money}</td>
<td>${tbl.phone}</td>
</tr>
</c:forEach>
</table>
练习:遍历一个表格