Hello Jsp
Hello Jsp
servlet输出数据的弊端
servlet方式返回数据,通过response对象获取输出流,将结果写入到相应体中。这种方式只适合数据量较小的情况,一旦数据量较大时,每次输出都需要重启一行,非常麻烦
PrintWriter out = request.getWriter();
out.print("result1");
out.print("result2");
out.print("result3");
JSP在执行时,会自动将文件内容写入响应体中,从而节省书写out.print()
格式
文件头
<%-- contentType:通知浏览器解析jsp的方式 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
语法规则
执行标记
使用普通文本是无法识别java代码的
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
int a = 10;
int b = 20;
a + b;
浏览器输出结果
int a = 10; int b = 20; a + b;
使用<%...%>
来标记java代码,只有在<%...%>
标记内部的代码才会识别为java代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
int a = 10;
int b = 10;
System.out.println(a + b); <%-- 将a+b输出到控制台 --%>
%>
在jsp内,所有的<%...%>
被当作一个整体
可以通过java代码控制页面输出
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
int age = 15;
if (age > 18) {
%>
<p style="margin:auto;text-align:center;color:red">欢迎进入</p>
<%
} else {
%>
<p style="margin:auto;text-align:center;color:red">未成年人禁止入内</p>
<%
}
%>
遍历集合
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="domain.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
List<User> list = new ArrayList();
list.add(new User("wsd", "1339813"));
list.add(new User("alice", "11032"));
%>
<table border="2px">
<tr>
<td>用户名</td>
<td>密码</td>
</tr>
<%
for (User user : list) {
%>
<tr>
<td><%=user.getUsername()%></td>
<td><%=user.getPassword()%></td>
</tr>
<%
}
%>
</table>
输出标记
使用<%=...%>
将结果输出到浏览器界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
int a = 10;
int b = 10;
%>
a + b = <%=a + b%>
执行结果
a + b = 20
导包标记
使用<%page import="..."%>
导入外部依赖包
<%-- 导入相关依赖 --%>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
<%-- 在jsp中使用List集合 --%>
List list = new ArrayList();
list.add("Wsd");
%>
从集合中获取第一个对象:<%=list.get(0)%>
内置对象
request
HttpServletRequest类型,负责在jsp文件运行时读取请求包信息,与servlet在请求转发过程中实现数据共享
请求urlhttp://localhost:8080/index.jsp?username=wsd
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String username = (String)request.getParameter("username");
%>
从OneServlet得到的共享数据:<%=username%>
session
jsp文件在运行时,可以通过session获取共享数据或添加共享数据
jsp1
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
session.setAttribute("username", "Wsd");
%>
jsp2
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String username = (String)session.getAttribute("username");
%>
获取到jsp1添加到session的共享对象:<%=username%>
application
全局作用域对象,当tomcat启动时创建,tomcat关闭时销毁
运行原理
servlet负责处理业务,并得到处理结果
jsp负责将servlet中处理结果写入到响应体
servlet工作完成后,一般通过请求转发方式,向tomcat申请调用jsp
数据共享
servlet将处理结果添加到请求作用域对象
jsp文件在运行时,从请求作用域对象得到处理结果
OneServlet:将数据写入request,并将请求转发到users.jsp
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List list = new ArrayList<User>();
list.add(new User("Wsd", "133813"));
list.add(new User("Alice", "11f1"));
request.setAttribute("userList", list);
request.getRequestDispatcher("/users.jsp").forward(request, response);
}
}
users.jsp
<%@ page import="java.util.*" %>
<%@ page import="domain.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<table border="2px">
<tr>
<td>用户名</td>
<td>密码</td>
</tr>
<%
List<User> userList = (List)request.getAttribute("userList");
for (User user : userList) {
%>
<tr>
<td><%=user.getUsername()%></td>
<td><%=user.getPassword()%></td>
</tr>
<%
}
%>
</table>
JSP运行原理
servlet规范中,只有servlet实现类才能被tomcat调用
Http服务器调用JSP文件步骤
1、Http服务器将JSP内容编辑为一个Servlet接口实现类
2、Http服务器将Servlet接口实现类编译为class文件
3、Http服务器负责创建这个class的实例对象,这个实例对象就是servlet实例对象
4、Http服务器通过Servlet实例对象调用jsp_service()
方法,将JSP文件的内容写道响应体
创建一个index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
hello jsp
项目发布后,可以在tomcat的work文件夹内看到index_jsp.java
以及编译过的index_jsp.class
class文件地址C:\Users\18119\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_9_0_37_JavaWeb\work\Catalina\localhost\JavaWeb_war_exploded\org\apache\jsp
考试题目管理系统
EL表达式
el工具包是由java技术开发的jar包,tomcat服务器本身自带了EL表达式工具包
jsp实现共享资源步骤过于繁琐
1、获取到共享对象
2、强制类型转换
3、输出
<%
String username = (String)request.getAttribute("username");
%>
<%=username%>
El表达式和JSP内置对象获取共享数据对比
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("name", "Wsd");
request.getSession().setAttribute("age", "21");
request.getServletContext().setAttribute("sex", "男");
request.getRequestDispatcher("/test.jsp").forward(request, response);
}
}
1、使用jsp内置对象实现信息共享
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String name = (String)request.getAttribute("name");
String age = (String)session.getAttribute("age");
String sex = (String)application.getAttribute("sex");
%>
姓名:<%=name%> <br>
年龄:<%=age%> <br>
性别:<%=sex%> <br>
2、使用El表达式获取共享对象
姓名:${requestScope.name}
年龄:${sessionScope.age}
性别:${applicationScope.sex}
命令格式
${作用域对象别名.共享数据}
El表达式是El工具包提供的一种特殊命令格式,负责在JSP文件上从作用域对象读取指定的共享数据并输出到响应体
JSP文件可以使用的作用域对象
类型 | 别名 | 说明 |
---|---|---|
ServletContext | application | 全局作用域对象 |
HttpSession | session | 会话作用域对象 |
HttpServletRequest | request | 请求作用域对象 |
PageContext | pageContext | 当前页作用域对象 |
注:PageContext是JSP独有的对象,Servlet中不存在。在当前页面作用域对象中存放的共享对象只能用于当前JSP文件中,不能共享给其他JSP文件使用。PageContext主要用于JSTL标签与JSP文件之间共享数据
EL表达式提供作用域对象
JSP | EL表达式 |
---|---|
application | ${applicationScope.共享数据名} |
session | ${sessionScope.共享数据名} |
request | ${requestScope.共享数据名} |
pageContext | ${pageContext.共享数据名} |
引用数据共享
常用的数据类型可以使用El表达式很方便的取出,对于引用数据类型,EL表达式也可以很方便的做到
对比
OneServlet,将用户对象存入请求作用域中
...
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = new User("Wsd", "0413");
request.setAttribute("user", user);
request.getRequestDispatcher("/test.jsp").forward(request, response);
}
}
使用jsp内置对象
<%@ page import="enity.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
User user = (User)request.getAttribute("user");
%>
用户姓名:<%=user.getUsername()%> <br>
用户密码:<%=user.getPassword()%>
使用EL表达式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
用户姓名:${requestScope.user.username} <br>
用户密码:${requestScope.user.password}
注意:使用EL表达式可以很方便的访问引用数据类型中的属性,但是不具备遍历集合的方法,无法读取集合数据进行输出
简化的El表达式
可以直接省略作用域对象
,直接使用${共享数据}
上面例子中的获取User
对象的简化版获取方式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
用户姓名:${user.username} <br>
用户密码:${user.password}
简化版的El表达式更加方便,但同时也有有一个隐患:如果不同作用域对象中添加了相同key
的对象,则不同作用域中的对象会发生覆盖
CPU执行指令采用分支预测算法,由于简化版的EL表达式没有指定作用域对象,所以
1、首先到pageContext
中定位共享数据,如果存在则直接输出并结束执行
2、如果PageContext
中没有定位成功,则到request
中定位共享数据,如果存在则直接输出并结束执行
2、如果request
中没有定位成功,则到session
中定位共享数据,如果存在则直接输出并结束执行
3、如果session
中没有定位成功,则到application
中定位共享数据,如果存在则直接输出并结束执行
5、如果application
中没有定位成功,则返回null
查询顺序:pageContext
--> request
--> session
--> application
所以当不同作用域中存储的key相同对象时
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = new User("Wsd", "0413");
request.setAttribute("user", user);
HttpSession session = request.getSession();
session.setAttribute("user", "133813");
request.getRequestDispatcher("/test.jsp").forward(request, response);
}
所以当使用简化的EL表达式获取user对象时,会获取到request作用域
中的User对象
用户姓名:Wsd
用户密码:0413
使用场景
简化从pageContext中读取共享和输出数据的难度,虽然EL表达式存在很多隐患,但是在开发过程中,为了节省时间,一般还是使用简化版
运算
传统的数据运算
OneServlet,向请求作用域中添加两个不同类型的数据
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("n1", "100");
request.setAttribute("n2", 50);
request.getRequestDispatcher("/test.jsp").forward(request, response);
}
使用EL表达式之间进行数学运算
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
结果为:${n1 + n2}
不用一个个的将属性从作用域对象中取出,再进行类型转换
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String n1 = (String)request.getAttribute("n1");
Integer n2 = (Integer)request.getAttribute("n2");
int res = Integer.parseInt(n1) + n2;
%>
结果为:<%=res%>
EL表达式支持的运算表达式
支持的运算 | 说明 |
---|---|
数学运算 | +、-、*、/、%、等 |
关系运算 | >、<、==、等 |
逻辑运算 | &&、||、! |
内置对象
param
命令格式:${param.请求参数名}
作用:通过请求对象读取请求响应包中的参数,并写入响应体
例:接收请求参数
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
欢迎${param.username}登录
向浏览器发送请求
http://localhost:8080/one?username=Wsd
展示jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
欢迎${param.username}登录
结果
欢迎Wsd登录
paramValues
命令格式:${paramValues.请求参数名[下标]}
作用:如果浏览器发送的请求参数是一个参数关联多个值,发送到服务端时则是数组的形式,通过paramValues
可以获取到这个数组,再通过下标的方式进行访问
例:接收请求参数数组
http://localhost:8080/one?enjoy=唱&enjoy=跳&enjoy=RAP
展示jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
爱好: <br>
${paramValues.enjoy[0]} <br>
${paramValues.enjoy[1]} <br>
${paramValues.enjoy[2]} <br>
结果
爱好:
唱
跳
RAP