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

posted @ 2021-02-14 09:51  INEEDSSD  阅读(147)  评论(0编辑  收藏  举报