Servlet作为服务器的小程序,为我们解决了业务问题(作为控制器)。但是,我们想要写出更接近“前端”的代码,需要我们了解JSP相关技术。

在JSP中,我们要了解:

  • JSP代码组成

    • 模板

    • 脚本元素(指令、动作、声明、scriptlet和表达式)

    • 标准动作和定制动作

  • 使用指令写JSP代码

    • page

    • include

    • tablib

  • JSP标准动作

    • include(运行时调用-单独的.class文件)

    • forward(跳转JSP、Servlet)

  • JSP内置对象

    • request

    • response

    • out

    • session

    • config

    • application

    • page

    • pageContext

    • exception

  • JSP的生命周期

    • 页面转换:JSP->Servlet

    • JSP页面编译

    • 加载类

    • 创建实例

    • jspinit

    • 使用_jspService

一个JSP示例:

<%@ page language="java" pageEncoding="utf-8"%>
<%@ page import="com.web.po.*"%>

<%-- 这是一个JSP注释 --%>
<%
    int number = 0;
%>
<%= number++1 %>

首先,我们要考虑的是,容器对我们的JSP页面做了什么,如何让JSP转换成Servlet的:

  • 小脚本里的代码会放在通用服务方法,变量为局部变量

  • 使用JSP声明的变量,会成为Servlet的类变量

容器,实际上,按照如下的步骤生成Servlet

  • 查看指令,转换相应的方法

  • 创建一个HttpServlet的子类

  • 检查声明,把变量写入类

  • 创建服务方法

  • 把HTML转换成流输出的方式

好了,该看一下JSP的生命周期了:

  • JSP文件被部署到Web容器里

  • 第一个请求到来,JSP文件被转换成.java

  • Java文件被编译成.class文件

  • 容器加载Servlet类

  • 实例化Servlet,调用servlet的jspInit()初始化

和Servlet一样,我们的JSP也是可以配置初始化参数的,我们需要在DD文件里这样写:

<servlet>
    <jsp-file>somefile</jsp-file>
    <init-param>
        <param-name></param-name>
        <param-value></param-value>
    </init-param>
</servlet>

或者,自己在JSP文件中写声明:

<%!
    public void jspInit(){
        // 在这里写初始化的逻辑代码
    }
%>

然后,我们的JSP中也是有作用域(PageContext中的枚举值):

  • APPLICATION_SCOPE

  • PAGE_SCOPE

  • REQUEST_SCOPE

  • SESSION_SCOPE

好了,终于可以聊聊JSP的指令,动作和内置对象了:
指令列表:

  • page(属性如下)

    • import

    • isThreadSafe

    • contentType

    • isErrorPage

    • errorPage

    • pageEncoding

    • 。。。。。。

  • taglib

  • include

其实,这些指令已经允许我们在JSP页面中书写Java代码,但是,为了后期维护,我们不应该写scriptlet。这就需要我们在DD中禁用小脚本

<web-app>
    <jsp-config>
        <jsp-property-group>
            <!-- 下面的配置对所有的JSP文件,都禁用Java小脚本 -->
            <url-pattern>*.jsp</url-pattern>
            <scripting-invalid>true</scripting-invalid>
        <jsp-property-group>
    </jsp-config>
<web-app>

不过,当我们写了太多的脚本,我们开始寻求无脚本页面,于是,JSP标准动作可以来帮忙:

JavaBean相关

  • jsp:useBean

  • jsp:setProperty

  • jsp:getProperty

  • jsp:param

<%-- 带体的useBean --%>
<jsp:useBean id="beanId" class="someClass" scope="someScope">
    <jsp:setProperty name="propertyName" value="propertyValue"/>
</jsp:useBean>

<%-- 使用多态的useBean --%>
<jsp:useBean id="xx" class="someClass" type="superClassName">
    
</jsp:useBean>

<%-- 使用param设置bean的属性 --%>
<jsp:useBean id="xx" class="xx" scope="someScope">
    <jsp:setProperty name="propertyName" param="propertyName"/>
</jsp:useBean>
<%-- 如果bean的属性和表单属性名一致,可以使用如下代码 --%>
<jsp:useBean id="xx" class="xx" scope="someScope">
    <jsp:setProperty name="beanName" property="*"/>
</jsp:useBean>

如果某个JavaBean的属性还是一个对象,我们就得写EL咯!

<%-- dot-operator --%>
${requestScope.name}
<%-- []-operator --%>
${requstScope.someList["0"]}

EL中有一些隐式对象,下面是其一览表:

  • 作用域

    • pageScope

    • requsetScope

    • sessionScope

    • applicationScope

  • 请求参数

    • param

    • paramValue

  • 请求首部

    • header

    • headerValues

  • cookie

  • initParam

  • pageContext

<%-- 下面是一个表单 --%>
<form action="result.jsp" method="post">
    用户名:<input type="text" name="username">
    食物1:<input type="text" name="food">
    食物2:<input type="text" name="food">
</form>
<%--  下面是result.jsp --%>
${param.username}
<%-- 使用paramValues获取多值参数 --%>
${paramValues.food[0]}
<%-- 获取头部信息 --%>
${header.host}

野原英雄
206 声望25 粉丝

一只小猿


引用和评论

0 条评论