Servlet、JSP

news2024/7/6 6:25:05

一、web服务器

1.1 常用服务器产品

  • Tomcat(Apache开源,主流的web服务器之一,多用于javaweb项目开发)

  • jetty(效率高于Tomcat)

  • WebLogic(Oracl 收费)

  • WebSpera(IBM)

  • Nginx(web静态资源服务器)

1.2 Tomcat简介

Tomcat是Apache开源组织共享的一个jakarta项目中的一个核心项,tomcat开源免费、支持java中的动态网页技术Servlet和JSP规范,且其技术先进、性能稳定因此Java开发者多使用Tomcat

1.3 Tomcat目录介绍

  • bin 存放可执行的二进制文件

  • conf 存放tomcat的配置文件

  • lib 存放服务器编译执行java代码的基础类库

  • logs 存放服务器的运行日志、记录服务器启动、运行异常及关闭等操作的记录

  • temp 临时目录,存放tomcat运行过程中临时文件

  • webapps 存放tomcat管理的web项目的目录,此目录中默认部署了tomcat管理器等几个web项目

  • work tomcat可以进行动态网页,动态网页就是在服务器将数据加载到网页生成的页面,此mukluk就是存放tomcat生成的文件

1.4 tomca无法启动原因启动和 关闭

Tomcat是基于java的web服务器,它运行以来JDK,因此安装Tomcat之前要确保计算机上安装了JDK并正确配置环境变量(JAVA_HOME)

1.5 web项目部署

将web项目交给tomcat管理,当用户访问tomcat时,tomcat可以将web项目中的资源响应给用户浏览器
  • 直接将web项目拷贝到tomcat的webapps目录(http访问路径就是项目名)

  • 将web项目的路径配置到tomcat中

在tomcat的conf\catalina\localhost目录中创建一个自定义xml文件

<!--path配置web项目的http访问路径 docBase配置web项目的目录路径-->
<Context path="/demo1" docBase="E:\javaweb\workspace\demo1"></Context>

1.6 Tomcat服务器请求响应流程

1.7 tomcat端口配置

默认端口是8080,可以通过conf/server.xml配置文件,修改服务器端口;
端口可以使1-65535中的数字,但是一般2000以下的很多端口被系统服务绑定,不建议使用。
80端口为浏览器默认访问端口,所以服务器修改端口为80后,浏览器无需添加端口也可访问

二、HTTP协议

浏览器与服务器之间进行网络通讯需要遵守HTTP协议

2.1 什么是HTTP协议

超文本传输协议是运行于TCP协议的基础之上、基于请求于响应模式、无状态的应用层协议,是互联网中应用最广泛的协议之一
  • TCP协议:基于连接的安全传输协议(客户端与服务器端建立连接,再通过连接发送数据)

  • UDP协议:基于广播/分发的非安全传输协议(不会建立网络连接)

2.2 HTTP协议的特点

  • 基于TCP协议:当浏览器与服务器进行通信时,会首先建立网络连接,通过网络连接进行通讯

短连接:在HTTP1.0中,浏览器向服务器发送请求,建立连接,但是这个连接只作用于浏览器和服务 器的一次请求响应,这次请求响应完成之后则断开连接

长连接:在HTTP1.1中,浏览器请求于服务器建立连接、进行请求和响应之后,会等待几秒钟,在这 几秒钟内如果浏览器有新的请求,则直接使用之前的这个连接进行请求和数据响应,如果过 了几秒钟没有新的请求,则将连接断开。

  • 请求和响应模式:首先由浏览器向服务器发送请求,服务器再对请求进行响应,如果没有浏览器的请求服务器时不会主动向浏览器进行响应。

  • 无状态:服务器不会感知同一客户端的多次请求(就是当服务器接收到客户端请求之后,不能识别这个客户端是否请求过我)

  • 简单灵活:实现简单、可以传输不同类型的数据(文本、文件。。。)

2.3 HTTP协议通信规则

HTTP协议就是请求和响应模式,浏览器向服务器发送请求时,需要遵守HTTP请求规则,服务器对浏览器进行响应时,也需要遵守HTTP响应规则

2.3.1 http请求规则

  • 可以通过浏览器的F12快捷键查看HTTP请求内容

  • 也可以自定HTTP服务器,接收浏览器请求,查看HTTP请求规则

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9998);
        Socket accept = serverSocket.accept();
        InputStream inputStream = accept.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String content = null;
        while(!(content = bufferedReader.readLine()).equals("")){
            System.out.println(content);
        }

        //模拟浏览器响应
        PrintWriter printWriter = new PrintWriter(accept.getOutputStream());

        //响应头
        printWriter.println("HTTP/1.1 200 OK");
        printWriter.println("Connection: keep-alive");
        printWriter.println("Content-Type: text/html; charset=utf-8");
        printWriter.println("Server: BWS/1.1");
        printWriter.println("Date: Mon, 27 Feb 2023 03:46:24 GMT");
        printWriter.println("Content-Length: 154");

        /空行
        printWriter.println("");
        
        //响应体
        printWriter.println("<!DOCTYPE html>");
        printWriter.println("<html>");
        printWriter.println("<head>");
        printWriter.println("<title>this is diy web page</title>");
        printWriter.println("</head>");
        printWriter.println("<body>");
        printWriter.println("123124");
        printWriter.println("</body>");
        printWriter.println("</html>");
        printWriter.flush();
        printWriter.close();
    }
  • 通过浏览器访问本地的9999端口,得到如下打印

2.3.2 http响应规则

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("www.cc-jewel.com",80);

        //模拟浏览器发送请求
        OutputStream outputStream = socket.getOutputStream();
        PrintWriter printWriter = new PrintWriter(outputStream);
        printWriter.println("GET / HTTP/1.1");
        printWriter.println("Host: www.cc-jewel.com:80");
        printWriter.println("Connection: keep-alive");
        printWriter.println("sec-ch-ua: \"Chromium\";v=\"110\", \"Not A(Brand\";v=\"24\", \"Google Chrome\";v=\"110\"");
        printWriter.println("sec-ch-ua-mobile: ?0");
        printWriter.println("sec-ch-ua-platform: \"Windows\"");
        printWriter.println("Upgrade-Insecure-Requests: 1");
        printWriter.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
        printWriter.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
        printWriter.println("Sec-Fetch-Site: none");
        printWriter.println("Sec-Fetch-Mode: navigate");
        printWriter.println("Sec-Fetch-User: ?1");
        printWriter.println("Sec-Fetch-Dest: document");
        printWriter.println("Accept-Encoding: gzip, deflate, br");
        printWriter.println("Accept-Language: zh-CN,zh;q=0.9");
        printWriter.println("");
        printWriter.flush();
        //获取百度响应
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String content = null;
        while((content = bufferedReader.readLine()) != null){
            System.out.println(content);
        }
    }

2.4 HTTP响应状态码

当浏览器向服务器发送请求,服务器对浏览器进行响应时,会响应给浏览器一个状态码,不同得状态吗标识服务器对请求得不同处理
  • 1XX 表示浏览器请求服务器,服务器未作任何操作

  • 2XX 表示服务器正常响应,并响应成功

  • 3XX 表示服务器只对浏览器得请求进行了部分处理,通知浏览器进行下一步操作

  • 4XX 表示浏览器端错误

  • 5XX 表示服务器端资源错误

2.4.1 常见状态码

  • 200 响应成功

  • 302 表示服务器资源临时重定向

  • 304 表示服务器资源没有变化

  • 404 访问得资源不存在

  • 500 访问得服务器端资源错误

三、Servlet

3.1 简介

Servlet是服务器端的java程序,能够接收HTTP请求,处理HTTP请求,并对HTTP请求进行响应的动态网页技术

Servlet是JavaEE(javaWeb)规范的一个重要组成部分

Servlet的作用:

  • 接收客户端的HTTP请求

  • 根据用户请求进行数据处理

  • 动态生成网页

  • 将生成的包含动态数据的网页响应给客户端

3.2 Java Web工程

Servlet是JavaEE规范的一部分,Servlet的开发需要依赖JavaEE环境,之前创建的单纯的Java应用已经不能满足Servlet开发所需要的环境需求
  • Java工程:只引入JDK的标准库(java SE)

  • Java web工程:引入java企业级开发环境(java EE)

3.2.1 IDEA创建web工程

  • 配置Tomcat

  • 选择web application项目框架及版本

3.2.2 web工程目录

3.3 创建Servlet

Servlet是一个java程序,是一个能够接收HTTP请求的java类,因此需要实现HTTP协议
在JavaEE库中有一个类 HttpServlet 实现了HTTP协议,我们创建的类只要继承这个httpServlet类,就实现HTTP协议,就能够接收HTTP请求
  • 创建一个类继承javax.servlet.http.HttpServlet

  • 继承HttpServlet类 就能够接收HTTP请求,我们把这样的类称为Servlet类,类以*****Servlet命令

  • 在创建的Servlet类中重写doGet 和doPost方法

3.4 配置Servlet

Servlet创建完成之后需要配置url访问路径,然后将web项目运行在tomcat之上,就能够通过配置的url访问Servlet类,Servlet自3.0规范开始支持两个配置方式
  • 基于web.xml 配置文件进行配置

  • 基于注解配置

3.4.1 基于web.xml配置servlet

  • 打开Java Web工程中 web/WEB/INF/web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--    servlet标签 配置类路径-->
    <servlet>
        <!--        配置与servlet-mapping 标签的匹配标识 理论上可以是任意字符串,一般建议与当前类名相同-->
        <servlet-name>bookListServlet</servlet-name>

        <!--    servlet类路径    -->
        <servlet-class>com.cpy.test1.BookListServlet</servlet-class>
    </servlet>

    <!--  servlet-mapping配置访问url  -->
    <servlet-mapping>
        <!--  servlet-mapping 与   servlet 中的 servlet-name 相互匹配   -->
        <servlet-name>bookListServlet</servlet-name>
        <!--    url-pattern 配置Servlet的访问路径,必须以/开头    -->
        <url-pattern>/book-list</url-pattern>
    </servlet-mapping>
</web-app>

3.4.2 基于注解配置servlet

在创建的Servlet类上添加 @WebServlet注解,在注解后的参数中配置url,url也必须以/开头
@WebServlet("/bookQuery")
public class BookQueryServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

3.5 IDEA部署web项目

通过IDEA将java web项目部署到Tomcat服务器,并运行Tomcat

3.5.1如果需要配置Tomcat服务器

  • File->Setting中做如下图选择

3.5.2 部署Web项目

  • 点击IDEA右上角

  • 添加Tomcat服务器

  • 部署项目

  • 配置项目访问路径

3.5.3 启动Tomcat

  • 播放按钮直接运行

  • 虫子按钮debug运行

3.5.4 Tomcat启动完成过程中的动作

  • 构建web项目

  • 将web项目拷贝到Tomcat

  • 启动Tomcat

  • 打开浏览器,访问当前项目首页

3.6 浏览器访问测试

通过浏览器发送HTTP请求,访问Tomcat中web项目的Servlet类

3.7 请求方式

Servlet中doGet和doPost是用来处理浏览器不同请求方式的HTTP请求,在HTTP协议中,HTTP请求有多种请求方式(get post delete put option 等),不同的请求方式传递的数据是不同的

3.7.1 get请求

Get请求服务器,传递的参数会拼接到URL后面,用?分割url和参数,多参数用&符号分割
  • get方式是明文提交,提交的数据量小,安全性差

  • get传输效率较高,浏览器地址栏输入网址,form的get ,ajax的get 采用get方式提交

3.7.2 Post请求

Post请求服务器,参数是通过请求正文(request body)进行传递的
  • post使用请求体传递数据,数据量大,安全性高

  • post效率较低,form 的 post,ajax的post采用post方式提交

四、Servlet原理解析

4.1 ServletAPI核心类和方法

4.2 Servlet类处理用户请求的流程

4.3 Servlet实例生命周期

Servlet实例的生命周期指Servlet类的实例从创建到销毁的过程
  • Servlet类时单实例 多线程的,一个Servlet类自始至终只会创建一个对象

  • 如果当前Servlet类没有配置<load-on-startup>当客户端第一次请求Servlet时,调用init创建当前Servlet类的实例,然后调用service-> doGet/doPost来处理用户请求,当请求再次达到时不调用init直接调用service方法

  • 如果当前Servlet类配置了<load-on-startup>,当服务器启动时就会执行init方法创建当前Servlet类实例。这样无论什么时候请求当前Servlet类 都不会再执行init方法。

  • 服务器关闭时,Servlet类的实例会被销毁

4.3.1 load-on-startup的两种方式

  • xml配置

    <servlet>
        <!--        配置与servlet-mapping 标签的匹配标识 理论上可以是任意字符串,一般建议与当前类名相同-->
        <servlet-name>bookListServlet</servlet-name>

        <!--    servlet类路径    -->
        <servlet-class>com.cpy.test1.BookListServlet</servlet-class>
        <!-- 配置启动加载,里面的数字就是服务器创建实例的顺序 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
  • 注解配置

@WebServlet(value="/bookQuery",loadOnStartup = 1)
public class BookQueryServlet extends HttpServlet 

4.4 线程安全问题

Servlet为单例模式,当多个客户端并发访问时,tomcat会创建多个线程,多线程使用同一个实例,可能会导致线程安全问题
  • 实现SingleThreadModel接口

实现 SingleThreadModel接口,每个线程都会创建Servlet实例,避免多线程使用同一Servlet实例。但这种方式会降低响应效率,增加服务器开销,不建议使用,已过时
@WebServlet(value="/bookQuery",loadOnStartup = 1)
public class BookQueryServlet extends HttpServlet implements SingleThreadModel 
  • 使用synchronized同步锁

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        synchronized (this){
            System.out.println("BookQueryServlet doGet");
            PrintWriter writer = resp.getWriter();
            writer.println("123124124");
            writer.flush();
            writer.close();
        }
    }
  • 在Servlet实例中尽量不使用全局对象

如果将变量定义为成员变量,则这个变量在多线程中式共享得,就有可能因为多线程同时修改这个变量导致并发问题,因此我们可以将变量定义在处理业务得doXX方法中,定义为局部变量后,每个线程都有属于自己得局部变量

五、Servlet开发技术

5.1 HttpServletRequest对象

客户端向服务器发送得请求信息都会被封装到HttpServletRequest对象,HttpServletRequest提供了多个方法,可以用于获取http请求中得数据(请求行 请求头 请求体)

5.1.1 HttpServletRequest对象的三种获取数据方式

getParameter()、getInputStream()和getReader() 三者都是从selvlet中request对象得到提交的数据

form表单中enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

描述

application/x-www-form-urlencoded

在发送前编码所有字符(默认)

multipart/form-data

不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。

text/plain

空格转换为 “+” 加号,但不对特殊字符编码。

  1. getInputStream()方法返回一个代表实体内容的输入流对象。

  1. getReader()方法返回一个代表实体内容的BufferedReader对象,实体内容的字节数据按照请求消息中指定的字符集编码转换成文本字符串。

  1. enctype=application/x- www-form-urlencoded. Servlet 的 API 提供了对这种 编码方式解码的支持,只需要调用 ServletRequest 类中的 getParameter()方法就可以得到用户表单中的字段和数据。但对于传输大块的二进制数据显得力不从心。

  • 注意事项

三种方式是冲突的,只能读取一次。混合使用会抛异常。

5.1.2 中文乱码

客户端向服务器的Servlet类提交数据中包含中文,可能会出现中文乱码问题

  1. 为什么会产生中文乱码问题

  • 客户端提交的数据通过网络发送到服务器,客户端通常会对传输数据通过会编码,服务器对数据进行解码;如果服务器使用的解码方式与网页的原始编码不一致,将会导致服务的解码出现乱码

  1. get方式提交数据的乱码问题

  • get方式提交的数据会拼接到URL后面进行传递,不同的浏览器处理方式是不一样的,有的浏览器会进行编码,有的浏览器则直接提交

  • 数据到达服务器之后,服务器会根据参数的编码方式对参数进行解码,如果没有编码则服务器直接接收,如果进行了服务器能够解析的编码,服务也会正常进行

  • 结论:GET方式提交请求行参数,是通过服务器进行处理的

  • 解决方案:在Tomcat的conf/server.xml中配置URL的编码方式

<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" 
redirectPort="8443" URIEncoding="utf-8">

  1. post方式提交数据的乱码问题

  • post方式提交表单数据是通过请求正文进行传递的,会对数据进行编码,tomcat会对URL传递的参数进行解码,但是不能对请求正文进行解码,因此我们需要在Servlet类中对接收数据之前对客户端提交的数据进行编码设置

request.setCharacterEncoding("utf-8");

5.2 HttpServletRespomse对象

HttpServletRespomse 对象 用户响应客户端请求

5.2.1 HttpServletRespomse对象常用方法

//设置响应状态
resp.setStatus(200);

//下面等价
resp.setHeader("Content-Type","text/html");
resp.setContentType("text/html");

//响应正文设置
resp.setCharacterEncoding("utf-8");
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter();
writer.println("123124124");
writer.flush();
writer.close();

5.3 Servlet动态网页案例

5.3.1 需求分析

5.3.2 项目环境搭建

  • 数据库环境准备

创建名为test的数据库

创建数据库表students grades courses

create  table students(
    stu_num char(5) primary key,
    stu_name varchar(20) not null,
    stu_gender char(2) not null,
    stu_pwd varchar(20) not null,
    stu_age int not null

);


create  table grades(
    gid int primary key auto_increment,
    snum char(5) not null,
    cid char(6) not null,
    score int not null
);

create table courses(
   course_id char(6) primary key,
   course_name varchar(50) not null
);

  • 创建Java web工程

  • 搭建JDBC环境

  1. 在web/WEB-INF创建lib目录,并在该目录导入JDBC所需驱动mysql-connector-java-8.0.15.jar、数据库连接池druid-1.1.8.jar、apache提供得工具包commons-dbutils-1.7.jar,在lib目录右键添加为库文件

  1. 配置连接池信息

在项目中创建一个com.cpy.students.utils

在包中创建druid.properties配置druid连接池信息

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
username=root
password=admin123
#初始化连接创建数据库连接池时默认初始化的连接个数
initialSize=10
#连接池最大连接数量
maxActive=30
#最小空闲连接
maxIdle=5
#超时等待时间
maxWait=3000

在utils包中创建数据库连接池工具类 DruidUtils

package com.cpy.students.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @ClassName DruidUtils
 * @Description 数据库连接池工具类
 * @Author cpy
 * @Date 2023/2/28 17:14
 * @Version 1.0.0
 **/
public class DruidUtils {
    //声明连接池对象
    private static DruidDataSource ds;

    static {
        Properties properties = new Properties();
        InputStream is = DruidUtils.class.getResourceAsStream("/database.properties");
        try {
            properties.load(is);
            //创建连接池
            ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //从数据库连接池中获取连接池对象
    public static Connection getConnection(){
        try {
            return ds.getConnection();//通过连接池获得连接对象
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static DataSource getDataSource(){
        return ds;
    }
}

5.3.3 完成数据操作

  • 创建com.cpy.students.dto.Student实体类

package com.cpy.students.dto;

import java.io.Serializable;

/**
 * @ClassName student
 * @Description 学生信息
 * @Author cpy
 * @Date 2023/2/28 17:30
 * @Version 1.0.0
 **/
public class Student implements Serializable {
    private String stuNum;
    private String stuName;
    private String stuGender;
    private String stuAge;
    private String stuPwd;

    public Student() {
    }

    public Student(String stuNum, String stuName, String stuGender, String stuAge, String stuPwd) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.stuGender = stuGender;
        this.stuAge = stuAge;
        this.stuPwd = stuPwd;
    }

    @Override
    public String toString() {
        return "student{" +
                "stuNum='" + stuNum + '\'' +
                ", stuName='" + stuName + '\'' +
                ", stuGender='" + stuGender + '\'' +
                ", stuAge='" + stuAge + '\'' +
                ", stuPwd='" + stuPwd + '\'' +
                '}';
    }
}
  • 创建com.cpy.students.dao.StudentDAO访问类

package com.cpy.students.dao;

import com.cpy.students.dto.Student;
import com.cpy.students.utils.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import java.sql.SQLException;

/**
 * @ClassName StudentDAO
 * @Description TODO
 * @Author cpy
 * @Date 2023/2/28 17:34
 * @Version 1.0.0
 **/
public class StudentDAO {
    /**
     * @Author cpy
     * @Description //TODO
     * @Date 17:44 2023/2/28
     * @param stuNum
     * @param stuPwd
     * @return 如果学号密码正确放回Student,否则返回null
     **/
    public Student queryStudentByNumAndPwd(String stuNum,String stuPwd){
        Student stu = null;
        try{
             String sql = "select stu_num stuNum,stu_name stuName,stu_gender stuGender,stu_age stuAge,stu_pwd stuPwd " +
                          "from students where stu_num=? and stu_pwd=?";
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
            stu = queryRunner.query(sql,new BeanHandler<Student>(Student.class),stuNum,stuPwd);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return stu;
    }
}

六、 JSP

6.1 jsp基础语法

java Server page 是sun公司提供的动态网页编程技术,是java web服务端的动态资源,相对于html允许在页面中嵌套jsp代码,为客户提供动态数据。
相对servlet而言,jsp除了可以用java代码动态生成数据,也可以对数据进行排版。不管jsp还是servlet,虽然都可以用于开发动态web资源,但人们把servlet作为web应用中控制器组件来使用,jsp作为数据的显示模板来使用,其实hsp就是一个servlet,当我们第一次访问jsp的时候,jsp引擎都会将这个jsp翻译成一个servlet,这个文件存放在tomcat中的work目录中。

6.1.1 注释

  • 显示注释法客户端代码可见隐

<%
// 单行注释
/*多行注释*/
%>
<!--html风格注释-->

  • 隐式注释法客户端代码不可见

<%-- jsp注释--%>

6.1.2 Scriptlet

jsp中一共有三种Scriptlet代码,都必须使用scriptlet标记起来
<% 可以写java代码 %> 生成的代码在servlet的service中
<%! 声明全局变量 方法 类 %> 生成的代码在servlet的类体中
<%= 输出表达式%> 生成的代码相当于out.print()输出
<%  
    String str="hello";
    System.out.println(str);
%> 
<%! 
   String member = "a member String";
 %>
<%=str %>

6.2 jsp的指令标签

6.2.1 include 静态包含

静态包含就是将内容进行了直接的替换,就是把此文件内容包含进去,只生成一个servlet,所以包含的页面以及被包含的页面中不能有同名的变量,会有命名冲突。运行效率高一些,但是耦合度较高,不够灵活
<%@include file="要包含的文件路径,可以是<%=表达式%>" %> <!--相对路径-->
<%@include file="header.jsp"%>
<%@include file="footer.html"%>

6.2.2 include 动态包含

动态包含在代码的编译阶段,包含和被包含部分是两个独立的部分,只有当运行时,才会动态包含进来,相当于方法的调用。会生成多个源码文件,可以定义同名变量,效率高,耦合度低。
<%--注意动态包含不需要传递参数时,include双标签质检不要床底任何内容,包括空格换行--%>
<jsp:include page="header.jsp"></jsp:include>
<jsp:include page="footer.jsp"></jsp:include>


<%--动态包含传递参数--%>
<jsp:include page="footer1.jsp">
    <jsp:param name="参数名,不支持表达式" value="参数值,支持表达式<%=表达式%>"/>
</jsp:include>

<%--对应界面获取传递的动态参数--%>
<%
    String para = request.getParameter("参数名");
%>

6.3 JSP中的跳转方式

6.3.1 服务器端跳转

<jsp:forword page="跳转的页面"></jsp:forword>

6.3.2 客户端跳转

<a href=""></a>

6.4 JSP的四大域对象

6.4.1 Page范围

pageContext:只在一个页面中保存属性,跳转之后无效.
<%
    pageContext.setAttribute("name","abc");
%>
<%
    pageContext.getAttribute("name");
%>

6.4.2 request范围

request:只在一次请求中保存,服务器跳转后依然有效.如果是客户端做跳转相当于两次请求,则第一个的请求将不存在。
<%
    request.setAttribute("name","abc");
%>
<%
    request.getAttribute("name");
%>

6.4.3 session范围

session:在一个会话范围内有效,物料何种跳转都可以使用
<%
    session.setAttribute("name","abc");
%>
<%
    session.getAttribute("name");
%>

6.3.4 application范围

application:在整个服务器保存
<%
    application.setAttribute("name","abc");
%>
<%
    application.getAttribute("name");
%>

6.5 EL表达式

6.5.1 EL表达式语法

为了使JSP写起来更加简单,它提供了在jsp中简化表达式的方法,让jsp的代码更加简化
EL表达式一般操作的都是域对象(pageContext,request,session,application),操作不了局部变量。EL默认的查找方式为从小到大查找,找到即可,当与对象全找完还是没有找到则放回空字符串""
  • 法语结构

${表达式}

<%
 pageContext.setAttribute("name","abc1");
request.setAttribute("name","abc2");
session.setAttribute("name","abc3");
application.setAttribute("name","abc4");
%>
<!--获取最小范围即pagecontext的name值-->
${name}
<!--获取指定范围的name值-->
${application.name}
  • 获取List

  • 获取Map

  • 获取javaBean

6.5.2 empty

字符串如果为空字符串""也会返回true

list如果没有添加值即size为0,也为true

map如果没有添加值,也为true

6.5.3 等值判断

6.5.4 算术运算

七、JSTL

7.1 标签的使用

JSP标准标签库,是一个定制标签类库的集合,用于解决一些常见的问题,例如迭代要给映射或者集合、条件测试、xml处理,甚至数据库和访问数据库操作等。 核心标签库: http://java.sun.com/jsp/jstl/core 包含web应用常见工作,比如:循环、表达式复制、基本输入输出等。 格式化标签库 http://java.sun.com/jsp/jstl/fmt 用来格式化显示数据的工作,比如:对不同区域的日期格式化等。
  • 格式:

<%@taglib uri="" prefix="" %> prefix可以是任意内容,但是建议使用标签库最后的名称比如fmt/core等
  • 使用步骤

  1. 下载jstl所需依赖jar: standard.jar、 jstl.jar

  1. 在项目的web目录下的WEB-INF中新建lib目录,将jar拷贝进去

  1. 选择file->project structure->modules->dependencies,选择右侧的+号,将对应的lib目录加载进来

  1. 在需要使用标签库的jsp页面引用进来

<%@tablib uri="http://java.sun.com/jsp/jstl/core" prefix="core"%>
<html>
<body>
<core:if test="${1==1}">
    Hello JSTL
</core:if>
</body>
</html>

7.2 常用标签

条件动作指令用于处理页面的输出结果依赖于某些输入值的情况,在java中利用if if。。。else 和switch语句来进行处理,在jstl中可以执行条件式动作指令的有4个:if choose when otthwise

7.2.1 if标签

如果条件为true则处理它的主体内容,测试结果保存在一个Boolean对象中,并创建一个限定变量来引用Boolean对象,可以利用var属性设置限域变量名,利用scope属性来指定七作用范围
  • 语法格式

<core:if test="boolean" var="string" scope="string">.
...
</core:if>
  • 属性

  1. test 条件判断,操作的是域对象,接收返回结果是boolean类型的值(必要属性)

  1. var 限域变量名,用来接受判断结果的值(可选属性)

  1. scope 限域变量名的范围(page(默认值)、request、session、application)(可选属性)

<%@tablib uri="http://java.sun.com/jsp/jstl/core" prefix="core"%>
<%
    request.setAttribute("num",10);
%>

<core:if test="num>10" var="flag" scope="request">
    数值大于10
</core:if>

<core:if test="num>100" var="flag" scope="request">
</core:if>
<%--如果使用session.flag则取不到--%>
${flag} -- $(request.flag)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/622951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cesium学习之旅1:cesium 基本介绍以及 cesium 的 hello world 程序

一&#xff1a;什么是Cesium Cesium 是一个跨平台、跨浏览器的展示三维地球和地图的 javascript 库。Cesium 使用WebGL 来进行硬件加速图形&#xff0c;使用时不需要任何插件支持&#xff0c;但是浏览器必须支持WebGL。Cesium是基于Apache2.0 许可的开源程序。它可以免费的用于…

代码随想录二刷 day16 | 二叉树之104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

day16 104.二叉树的最大深度559.n叉树的最大深度111.二叉树的最小深度222.完全二叉树的节点个数 104.二叉树的最大深度 题目链接 解题思路&#xff1a;本题中根节点的高度就是最大深度 二叉树节点的深度&#xff1a; 指从根节点到该节点的最长简单路径边的条数或者节点数&…

TensorFlow项目练手——天气预测

项目介绍 通过以往的天气数据和实际天气温度&#xff0c;做一次回归预测&#xff0c;模型的输入是当前的所有特征值&#xff0c;而模型的输出是当天的实际天气温度 字段分析 目前已有的数据有348条svc数据&#xff0c;他们的字段分别代表 year&#xff1a;年month&#xff…

美客多卖家攻略:养号技巧分享

在跨境电商平台上成功运营并建立起具有竞争力的店铺并不容易。美客多作为一个颇具影响力的平台&#xff0c;更需要卖家们仔细研究和精心运营。在这里&#xff0c;我将分享一些秘诀&#xff0c;这些秘诀是在我自养号过程中总结出来的&#xff0c;有助于增加销量并提升店铺的排名…

高级数据分析师岗位的职责描述

高级数据分析师岗位的职责描述1 职责&#xff1a; 1.搭建和完善数据中心的数据指标体系与监控预测体系&#xff0c;并推动系统化实现; 2.负责对市场、行业、竞争对手、产品、客户、业务运营等方面数据的收集、分析&#xff0c;完成整理出分析报告、提供数据支持、分析建议; 3.对…

AI 写的高考作文,你打几分?

又是一年高考时&#xff0c;高考真的是人生的一件大事&#xff0c;毕业这么多年&#xff0c;每次看到高考相关信息&#xff0c;还是会不由自主的点进来&#xff0c;其中语文的作文是每年大伙津津乐道的话题。 树先生今天就收到了某条小秘书的【邀请函】&#xff0c;邀请参与「…

Elasticsearch:实用指南

我们将更多地讨论使用 Elasticsearch 的最佳实践。这些做法是一般性建议&#xff0c;可以应用于任何用例。 让我们开始吧。 Bulk Requests 批量 API 使得在单个 API 调用中执行许多索引/删除操作成为可能。 这可以大大增加索引速度。 每个子请求都是独立执行的&#xff0c;因此…

Elasticsearch8.6.0安装

Elasticsearch 8.5.0 安装 Elasticsearch 简介Elasticsearch 8.6.0 安装创建网络拉取镜像运行镜像设置密码修改kibana配置绑定ES代码绑定&#xff1a;手动绑定&#xff1a; 配置ik分词器扩展词词典停用词词典 Elasticsearch 简介 Elasticsearch&#xff08;ES&#xff09; 是一…

Redis搭建分片集群

一、什么是Redis分片集群 1、概念 Redis分片集群是用于将Redis的数据分布在多个Redis节点上的分布式系统。通过分片集群&#xff0c;可以将数据分成多个部分&#xff0c;并将每个部分存储在不同的节点上&#xff0c;以便实现Redis的高可用性和高性能。 2、Redis分片集群原理…

写字楼里的「连接」智慧,撬起万亿新赛道

【潮汐商业评论/原创】 对于新入职的Cherry来说&#xff0c;在新公司上班的体验也是全新的。 每天上班&#xff0c;尚不熟悉的她可以在互动屏的指导下精准找到目的地。办公室的温度、湿度和空气质量&#xff0c;会随着天气条件和人员的密集程度相应调整。休息时Cherry抬头就能…

nc/netcat使用

目录 一、前言1.netcat是什么2.netcat有什么用 二、netcat的使用1.程序文件2.作为HTTP客户端3.作为HTTP服务端4.文件传输 三、问题与思考四、小结 一、前言 1.netcat是什么 netcat是一个基于命令行的网络调试和开发工具。对于windows和linux操作系统中都有适配的程序包,程序文…

AcWing算法提高课-1.3.13机器分配

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 本题链接&#xff08;AcWing&#xff09; 点这里 题目描述 总公司拥有 M M M 台 相同 的高效设备&#xff0c;准备分给下属的 N N N 个分公司。 各分公司若获得这些设备&#xff0c;可以为…

Linux - 第24节 - Linux高级IO(三)

1.Reactor模式 1.1.Reactor模式的定义 Reactor反应器模式&#xff0c;也叫做分发者模式或通知者模式&#xff0c;是一种将就绪事件派发给对应服务处理程序的事件设计模式。 1.2.Reactor模式的角色构成 Reactor主要由以下五个角色构成&#xff1a; 角色解释Handle&#xff08;句…

LVS-DR负载群集的优势和部署实例(我们都会在各自喜欢的事情里变得可爱)

文章目录 一、DR模式数据包流向分析二、DR模式的特点三、DR模式中需要解决的问题问题1解决方式 问题2解决方式 四、LVS-DR部署实例1.配置NFS共享存储器2.配置节点web服务&#xff08;两台的配置相同&#xff09;3.配置LVS负载调度器 一、DR模式数据包流向分析 1.Client 客户端…

【Hello MySQL】数据库基础

目录 1. 什么是数据库 2. 主流数据库 3. MySQL的基本使用 3.1 MySQL安装 3.2 连接 MySQL 服务器 3.3 退出 MySQL 服务器 3.4 服务器&#xff0c;数据库&#xff0c;表关系 3.5 MySQL的配置 4. MySQL架构 5. SQL分类 6. 存储引擎 6.1 存储引擎 6.2 查看存储引擎 6.3 存储引擎对…

Vue.js 中的 $nextTick 方法是什么?有什么作用?

Vue.js 中的 $nextTick 方法是什么&#xff1f; 在 Vue.js 中&#xff0c;$nextTick 方法是一个非常有用的工具&#xff0c;它可以让我们在下一个 DOM 更新周期之前执行回调函数。这个方法可以用于很多场景&#xff0c;比如在 Vue 实例数据改变之后&#xff0c;立即获取更新后…

肠道重要菌属——Dorea菌,减肥过敏要重视它?

谷禾健康 认识 Dorea菌 Dorea菌属于厚壁菌门毛螺菌科&#xff0c;广泛存在于人体肠道内&#xff0c;谷禾数据显示该菌在人群的检出率超89%。该菌最早也是从人体粪便中分离出来。 “Dorea” 目前没有一个确定的译名&#xff0c;Dorea是以法国微生物学家 Joel Dor 的名字命名&…

进入流程化管理不再是奢望,开源快速开发框架助你梦想成真!

在数字化进程快速发展的今天&#xff0c;流程化管理是企业做强做大的重要一步。如何实现流程化管理&#xff1f;如何实现数字化发展目标&#xff1f;这些问题都是值得每一个企业深思的重要课题。开源快速开发框架是一种快速帮助企业提质增效的平台软件&#xff0c;可以让每一个…

使用gcc展示完整的编译过程(gcc预处理模式、编译模式、汇编模式、连接模式)

最近在了解 clang/llvm 的时候突然发现一件事&#xff1a;gcc是一个工具集合&#xff0c;包含了或者调用将程序源代码转换成可执行程序文件的所有工具&#xff0c;而不只是简单的编译器。这帮助我对“编译器”有了更深刻的理解&#xff0c;所以写下本文作为记录。 关于“编译器…

如何用Web服务组件IIS免费搭建站点,并实现外网远程访问?

作为一名程序猿&#xff0c;经常会有搭建网站的需求&#xff0c;或被朋友要求帮忙着搭建网站&#xff0c;但是如果将网站建设在个人电脑或公司的服务器上&#xff0c;面临的问题是&#xff0c;没有公网IP或屏蔽了外网的80端口&#xff0c;在外网环境下就无法直接内网的网站&…