javaweb基础知识整理

1、项目基本结构

在这里插放入图片描述
代码分层:

1.1、entity层(model层,domain层)

简称实体层用于存放我们的实体类,类中定义了多个类属性,并与数据库表的字段保持一致,一张表对应一个类。

1.2、mapper层(dao层)

介绍: 数据持久层,先设计接口,然后在配置文件中进行配置其实现的关联。对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的。
作用:该层的作用为访问数据库,向数据库发送sql语句,完成数据的增删改查任务。
持久化操作: 数据持久化操作就是指,把数据放到持久化的介质中,同时提供增删改查操作。

1.3、Service层

用来存放业务逻辑处理,也是一些关于数据库处理的操作,但不是直接和数据库打交道
可以在Service层调用dao层的接口进行业务逻辑应用的处理。

1.4、until层

工具层,此项目把链接数据库的操作放在此处,如图
在这里插入图片描述

2、Tomcat的使用

转载:https://blog.youkuaiyun.com/qq_42146402/article/details/127584276

2.1 web服务器

Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。最主流的三个Web服务器是Apache、 Nginx 、IIS。

2.2 Tomcat

Tomcat 是一个Web应用服务器,Tomcat是Apache 服务器的扩展,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。

2.3 Tomcat目录结构

在这里插入图片描述
Tomcat目录介绍:

  • bin:专门用来存放 Tomcat 服务器的可执行程序
  • conf:专门用来存放 Tocmat 服务器的配置文件
  • lib:专门用来存放 Tomcat 服务器的 jar 包
  • logs:专门用来存放 Tomcat 服务器运行时输出的日记信息
  • temp:专门用来存放 Tomcdat 运行时产生的临时数据
  • webapps:专门用来存放部署的 Web 工程。
  • work:是 Tomcat工作时的目录,用来存放 Tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session 钝化的目录

2.4、修改Tomcat的端口号和主机名称

Tomcat 默认的端口号是:8080,要想修改Tomcat的端口号,找到 Tomcat 目录下的 conf 目录,再找到 server.xml 配置文件:
在这里插入图片描述
找到如下位置修改port值(端口号):
在这里插入图片描述
找到如下位置修改主机名称:
在这里插入图片描述

2.5、在idea配置Tomcat

  • (1)打开IDEA,创建一个Web项目
    在这里插入图片描述
  • (2) 配置Tomcat服务器在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
  • (3) 点击启动按钮启动Tomcat服务器,在浏览器中输入网址http://localhost:8080/即可在开发阶段访问网站

在这里插入图片描述

3、数据库链接(JDBC)

3.1、数据库驱动

我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。
在这里插入图片描述

3.2、JDBC简介

SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范(接口),称之为JDBC。这套接口由数据库厂商去实现,这样,开发人员只需要学习jdbc接口,并通过jdbc加载具体的驱动,就可以操作数据库。
在这里插入图片描述

3.3、异常处理

1)、什么是异常

错误产生于没有实现预料到的各种情况,或是超过了程序员可控制范围的环境因素。
常见的异常:算术异常、数组越界、空指针

2)、如何捕获异常
try{
        // 可能产生异常错误的语句
}catch( ExceptionTypeOne  e){
        // 对异常 ExceptionTypeOne 的处理语句
}catch ( ExceptionTypeTwo e) {
        // 对ExceptionTypeTwo 的处理语句
}
...........
finally {
        // 语句块
}
  • finally为异常处理的最后执行部分,无论前面的catch是否被捕捉,finally语句都会被执行
3)、常见的异常

java内部提供了一些异常,用来描述经常发生的错误,其中,有的需要程序员极性捕捉处理或声明抛出。有的是由java虚拟机自动进行捕捉

java常见的异常类如表:
在这里插入图片描述

4)、运行时异常

java类库的每个包中都定义了异常类,所有的类都是Throwable的子类,Throwable派生出两个子类,分别是Exception 和 Error 类。 Error 类及其子类用来描述java运行系统中的内部错误以及资源消耗的错误。
Exception类异常通过捕捉后程序可以继续正常执行。

Throwable 是异常处理体系的顶层类,派生除了Error 和 Exception 两个重要的子类。Error 指的是java虚拟机无法解决的严重问题,例如jvm内部错误,资源耗尽等等,其代表为: StackOverflowError 和 OutOfMemoryError。

Exception 异常类为程序员可以正常捕捉并处理的异常。
在这里插入图片描述

5)、异常处理流程

(1)程序先执行 try 中的代码 如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 . 如果找到匹配的异常类型, 就会执行 catch 中的代码 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者 .
(2)无论是否找到匹配的异常类型, finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
(3)如果上层调用者也没有处理的了异常, 就继续向上传递 . 一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止。

3.4、jdbc程序示例

(简要概括: Properties类是 键和值均为字符串的可以永久存储到文件中的key-value集合
java.util.Properties类表示一组持久的属性,是Hashtable的子类。 Properties可以保存到流中或从流中加载,可以保存到后缀名为properties的文件中。 属性列表中的每个键及其对应的值都是一个字符串。 即键和值都是String类型。)

database.properties如下

dirver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/edudb
user = root
password = 123456

DbUtil类:

package com.itdj.edu.Util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class DbUtil {
    private static String dirver;
    private static String url;
    private static String user;
    private static String password;

    public Connection connection = null;

    static {
        try {
            Properties properties = new Properties();
            /*类加载器来进行配置文件的载入*/
            InputStream inputStream = DbUtil.class.getClassLoader().getResourceAsStream("database.properties");
            properties.load(inputStream);
            /*获取驱动、url等*/
            dirver = properties.getProperty("dirver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
        } catch (IOException e) {   //输入输出异常
            throw new RuntimeException(e);  //抛出运行时异常,程序可以正常捕捉并处理的异常
        }
    }

    //获取链接对象
    public Connection getConnection() {
        Connection connection = null;
        try {
            //1.注册驱动
            Class.forName(dirver);
            //2、获取数据库连接对象connection
            connection = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) { //未找到相应的类异常
            throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
        } catch (SQLException e) { //操作数据库异常类
            throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
        }
        return connection;
    }

    //释放资源
    public void closeAll(Connection connection, Statement statement, ResultSet resultSet){

        try {

            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if(connection != null) {
                connection.close();
            }
        } catch (SQLException e) { //操作数据库异常类
            throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
        }
    }


    public int executeUpdate( String sql, Object[] params){//sql为执行语句,params为填充参数
        /*PreperedStatement是Statement的子类,相对于Statement对象而言:PreperedStatement可以避免SQL注入的问题。*/
        PreparedStatement preparedStatement = null;
        int num = 0;
        try {
            connection = getConnection();
            preparedStatement = connection.prepareStatement(sql);//1、获取preparedStatement
            for (int i = 0; i < params.length; i++) {
                preparedStatement.setObject(i+1,params[i]);//2、设置参数
            }
            num = preparedStatement.executeUpdate();//3、执行sql语句
        } catch (SQLException e) {//操作数据库异常类
            throw new RuntimeException(e);//抛出运行时异常,程序可以正常捕捉并处理的异常
        } finally { //无论是否发现异常此处都会执行,释放资源
            closeAll(connection, preparedStatement, null);
        }
        return num;
    }
}

3.5、Druid连接池

Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。
要使用Druid连接池,首先把jar包导入项目,通过druid.properties配置文件进行配置,常用的参数如下
在这里插入图片描述
db.properties如下

dirver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/edudb
user = root
password = 123456
initalSize=5
maxActive=10
maxWait=5000

DsUtil类:

package com.itdj.edu.Util;

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.*;
import java.util.Properties;

public class DsUtil {
    public Connection connection = null;

    private static DataSource dataSource;

    static {
        try {
            Properties properties = new Properties();
            /*类加载器来进行配置文件的载入*/
            InputStream inputStream = DsUtil.class.getClassLoader().getResourceAsStream("ds.properties");
            properties.load(inputStream);
            /*获取连接池对象*/
            dataSource = DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //获取链接对象
    public Connection getConnection() {
        try {
            /*数据源(DataSource)即数据来源,调用DataSource.getConnection(),即可获取一个连接,而无需关心连到哪个数据库,用户名/密码是什么.*/
            dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return connection;
    }

    //释放资源
    public void closeAll(Connection connection, Statement statement, ResultSet resultSet){

        try {

            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if(connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    public int executeUpdate( String sql, Object[] params){
        PreparedStatement preparedStatement = null;
        int num = 0;
        try {
            connection = getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                preparedStatement.setObject(i+1,params[i]);
            }
            num = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            closeAll(connection, preparedStatement, null);
        }
        return num;
    }
}

3.6、操作数据库增删改查

package com.itbbj.bbs.dao.impl;

import com.itbbj.bbs.dao.UserDao;
import com.itbbj.bbs.domain.User;
import com.itbbj.bbs.util.DbUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class UserDaoImpl implements UserDao {
    private DbUtil dbUtil = new DbUtil();
    @Override
    public int insert(User user) {
        String sql = "INSERT INTO USER(userName,PASSWORD,email) VALUES (?,?,?)";
        Object[] params = {user.getUserName(),user.getPassword(),user.getEmail()};
        int num = dbUtil.executeUpdate(sql, params);
        return num;
    }

    @Override
    public int update(User user) {
        String sql = "UPDATE USER SET userName = ?,PASSWORD = ?,email = ? WHERE id = ?";
        Object[] params = {user.getUserName(),user.getPassword(),user.getEmail(),user.getId()};
        int num = dbUtil.executeUpdate(sql, params);
        return num;
    }

    @Override
    public int delete(int id) {
        String sql = "DELETE FROM USER WHERE id = ?";
        Object[] params = {id};
        int num = dbUtil.executeUpdate(sql, params);
        return num;
    }

    @Override
    public List<User> getUserList() {
        Connection connection = dbUtil.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        List<User> userList = null;
        try {
            String sql = "select * from user";
            preparedStatement = connection.prepareStatement(sql);
            rs = preparedStatement.executeQuery();
            userList = null;

            userList = new ArrayList<>();
            User user = null;

            while (rs.next())
            {
                int id = rs.getInt(1);
                String userName = rs.getString("userName");
                String password = rs.getString("password");
                String email = rs.getString("email");
                user = new User(id, userName, password,email);
                userList.add(user);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            dbUtil.closeAll(connection,preparedStatement,rs);
        }

        return userList;
    }

4、HTML

4.1、什么是HTTP

HTTP(超文本传输协议)是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。

HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。

4.2、Http请求

客户端——>发请求——>服务器
一个HTTP请求报文由3个部分组成:

  • 请求行(request line)
  • 请求头部(headers)
  • 请求体(request body)

1.请求行

以访问百度为例:
在这里插入图片描述

Request URL:请求地址
Request Method:请求方式,一般是GET/POST
Status Code:状态码:200表示成功,404表示没有找到资源,500表示服务器错误....
Remote Address:远程地址
  • 请求行中的请求方式:GET
  • 请求方式:GET,POST,HEAD,DELETE,PUT,TRACT…
    GET:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但是高效
    POST:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但是不高效

2、请求头部

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机

3、请求体
请求体是将一个页面表单中的组件值通过param1=value1¶m2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1¶m2=value2”的方式传递请求参数。

4.3、HTML基础语法

4.4、CSS样式

4.5、javaScript

5、Servlet

5.1、什么是Servlet

  • Servlet是sun公司开发动态web的一门技术
  • Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

下图显示了 Servlet 在 Web 应用程序中的位置。
在这里插入图片描述

5.2、Servlet作用

  • 接收用户端发来的请求
  • 调用其他java程序来处理请求
  • 将处理结果,返回到服务器中

5.3、servlet的使用

1)、web.xml注册

我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径。

    <!--    注册servlet-->
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.itdj.news.servlet.LoginServlet</servlet-class>
    </servlet>
    <!--    servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
2)、注解

Servlet3.0提供了注解(annotation),我们可以不用再web.xml里面配置servlet,只需要加上@WebServlet注解就可以修改该servlet的属性了。web.xml可以配置的servlet属性,在@WebServlet中都可以配置。

@WebServlet 注解的属性,如下
在这里插入图片描述

使用 @WebServlet 注解

@WebServlet(​urlPatterns = “/MyServlet”)。
@Web​Servlet(“/MyServlet”) 省略了 urlPatterns 属性名
3)、@WebServlet 注解 和 web.xml 的区别

使用 web.xml 或 @WebServlet 注解都可以配置 Servlet
@WebServlet 注解配置 Servlet
优点:@WebServlet 直接在 Servlet 类中使用,代码量少,配置简单。每个类只关注自身业务逻辑,与其他 Servlet 类互不干扰,适合多人同时开发。
缺点:Servlet 较多时,每个 Servlet 的配置分布在各自的类中,不便于查找和修改。

web.xml 配置文件配置 Servlet
优点:集中管理 Servlet 的配置,便于查找和修改。
缺点:代码较繁琐,可读性不强,不易于理解。

4)、servlet实例

Servlet 是服务 HTTP 请求并实现 javax.servlet.Servlet 接口的 Java 类。Web 应用程序开发人员通常编写 Servlet 来扩展 javax.servlet.http.HttpServlet,并实现 Servlet 接口的抽象类专门用来处理 HTTP 请求。

// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

@WebServlet( value = "/helloWorld")
// 扩展 HttpServlet 类
public class HelloWorld extends HttpServlet {
 
  private String message;

  public void init() throws ServletException
  {
      // 执行必需的初始化
      message = "Hello World";
  }

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {
      // 设置响应内容类型
      response.setContentType("text/html");

      // 实际的逻辑是在这里
      PrintWriter out = response.getWriter();
      out.println("<h1>" + message + "</h1>");
  }
  
  public void destroy()
  {
      // 什么也不做
  }
}
*servlet生命周期

原文链接
Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

service() 方法
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

下面是该方法的特征:

public void service(ServletRequest request, 
                    ServletResponse response) 
      throws ServletException, IOException{
}

service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。

doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。

doGet() 方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

doPost() 方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

public void doPost(HttpServletRequest request,
                   HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}
*认识HttpServletRequest

HttpServletRequest的核心方法
在这里插入图片描述

**认识部分方法
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 16:57
 */
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder result=new StringBuilder();
        result.append(req.getProtocol());
        result.append("<br>");
        result.append(req.getMethod());
        result.append("<br>");
        result.append(req.getRequestURI());
        result.append("<br>");
        result.append(req.getQueryString());
        result.append("<br>");
        result.append(req.getContextPath());
        result.append("<br>");

        result.append("=============================");


    /*    Enumeration<String>  headerNames=req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String headerName=headerNames.nextElement();
            String headerValue=req.getHeader(headerName);
            result.append(headerName+":"+headerValue+"<br>");
        }*/
       //设置响应格式便于让浏览器解析
       resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write(result.toString());//转换成字符串的形式


    }
}


运行截图
在这里插入图片描述

**使用 Servlet 读取表单数据

原文链接
Servlet 处理表单数据,这些数据会根据不同的情况使用不同的方法自动解析:

  • getParameter():您可以调用 request.getParameter() 方法来获取表单参数的值。
  • getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框。
  • getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法。

简单实例(getParameter)
login.jsp
由表单的method可以看出这是post请求

<form method="post" action="<%= request.getContextPath()%>/Login">
    <table border="0" align="center">
        <tr>
            <td>用户名: </td>
            <td><input type="text" name="userName"></td>
        </tr>
        <tr>
            <td>密码: </td>
            <td><input type="text" name="pwd"></td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="POST请求">
        </tr>
    </table>
</form>

LoginServlet

package com.itdj.news.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet( value = "/Login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

                   doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Demo1Servlet::Post请求");
        request.setCharacterEncoding("UTF-8");
        String userName = request.getParameter("userName");//获取页面userName的值
        String pwd = request.getParameter("pwd");//获取页面pwd的值

        if("sa".equals(userName) && "sa".equals(pwd)){ //判断是否等于字符串"sa"
            Cookie cookieUserName = new Cookie("userName", "sa");
            cookieUserName.setMaxAge(6);
            response.addCookie(cookieUserName);
            response.sendRedirect("d1/welcome.jsp");
        }else{
            response.sendRedirect("d1/login.jsp");
        }
    }
}
*认识HttpServletResponse

核心方法
在这里插入图片描述

**认识部分方法
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 20:46
 */
@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
        resp.setStatus(200);//为响应设置状态
        resp.setContentType("text/html charset=utf8");//设置发送到客户端的响应的内容类型
        resp.getWriter().write("返回200响应");//往body写入文本格式数据

		resp.setHeader("Refresh","1");//设置每秒刷新一次
        resp.getWriter().write("time="+System.currentTimeMillis());//往body写入文本格式数据
        
        resp.sendRedirect("https://www.bidu.com");//重定向
    }
}
*请求转发和重定向(Web开发中用来处理页面跳转的方式)

原文链接
转发(Forward)内部流程

在这里插入图片描述
第一个ServletA接收到了浏览器端的请求,进行了一定的处理,然后没有立即对请求进行响应,而是将请求“交给下一个ServletB”继续处理,下一个ServletB处理完成之后对浏览器进行了响应。在服务器内部将请求“交给”其它组件继续处理就是请求的转发。

protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletExceptio ,IOException {

//1.使用RequestDispatcher对象封装目标资源的虚拟路径

RequestDispatcher dispatcher = request.getRequestDispatcher("/index.html");

//2.调用RequestDispatcher对象的forward()方法“前往”目标资源

//[注意:传入的参数必须是传递给当前Servlet的service方法的

//那两个ServletRequest和ServletResponse对象]

dispatcher.forward(request,response);}

重定向(Redirect)内部执行流程
在这里插入图片描述
第一个ServletA接收到了浏览器端的请求,进行了一定的处理,然后给浏览器一个特殊的响应消息,这个特殊的响应消息会通知浏览器去发送一个请求request2,去访问另外一个资源ServletB,这个动作是服务器和浏览器自动完成的,最终由ServletB做出响应。

response.sendRedirect(“success.html”);
*HTTP状态码

HTTP状态码可以分为五大类,它们分别是:

一、100-199,信息状态码。

此类状态码一般不会直接展示给用户(对用户透明)。

目前已定义的成功状态码有100、101。

二、200-299,成功状态码。

此类状态码一般不会直接展示给用户。如果我们在访问网站时收到成功状态码,则将看到网站的具体内容。

目前已定义的成功状态码有200、201、202、203、204、205、206。

三、300-399,重定向状态码。

此类状态码一般不会直接展示给用户,但用户可能看到网址自动发生改变。

目前已定义的重定向状态码有300、301、302、303、304、305、306、307。

四、400-499,客户端错误状态码。

此类状态码一般直接或者以友好的方式展示给用户,出现该状态码则意味着用户的操作存在错误。

目前已定义的客户端错误状态码有400、401、403、404、405、406、407、408、409、410、411、412、413、414、415、416、417。

五、500-599,服务器错误状态码。

此类状态码一般直接或者以友好的方式展示给用户,出现该状态码则意味着服务器发生错误。

目前已定义的服务器错误状态码有500、501、502、503、504、505。

其中,状态码404尤为常见,值得我们重点了解。

状态码404,一般显示为404 Not Found,表示无法在服务器上找到相应的资源。此状态码出现的原因主要有用户输入了错误的网址、服务器管理员移动或者删除了相关的资源。目前,很多网站对该状态码的显示网页进行了特殊设计,使得用户获得了更好的体验。

示例:

// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.servlet.annotation.WebServlet;

@WebServlet("/showError")
// 扩展 HttpServlet 类
public class showError extends HttpServlet {
 
  // 处理 GET 方法请求的方法
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
            throws ServletException, IOException
  {
      // 设置错误代码和原因
      response.sendError(407, "Need authentication!!!" );
  }
  // 处理 POST 方法请求的方法
  public void doPost(HttpServletRequest request,
                     HttpServletResponse response)
      throws ServletException, IOException {
     doGet(request, response);
  }
}

在这里插入图片描述

*Cookie & Session
**关于 Http 无状态的理解

什么 Http 无状态:

  • 服务器不会保留客户端交易的任何状态和数据,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接,这就意味着服务器无法从连接上跟踪会话。也就是指用户每次发起的请求之间是没有相关性的,每次的请求结束就结束了,不会在做任何数据的存储。

Http 请求的无状态带来的问题和影响:

  • 比如用户登录以后切换到别的界面进行操作,服务器端根本无法判别是哪个用户登录的,每次进行页面跳转的时候都要重新登录。

如何解决 Http 请求的无状态的问题:

  • 1:Session(服务器端)
  • 2:Cookie(客户端)
**Cookie & Session的工作原理
  • Session 原理: 其实是一种服务端的数据存储技术,存储在 StandardSession 类的 ConcurrentHashMap 集合中。为了维护每个请求的数据关系,会生成一个 jsessionid 并通过 Cookie写入客户端。后面在浏览器的每个请求的过程中都会比较请求的域和 Cookie 的域是否相同,如果相同,浏览器会把所有 Cookie 中存放的key 一起打包,放入到请求头中,发送给服务器。然后服务器会根据 request 对象解析请求头中 Cookie,如果该数据信息 jsessionid 和请求头中 Cookie 里 jsessionid 名字且值都相同,就直接返回一个 Session对象,如果找不到,说明会话已经失效。
  • Cookie 原理: 其实是一种客户端的数据存储技术,它会把数据写入到浏览器中,不会占用服务器的内存,所以在很多时候,如果仅仅只是临时的保存一些数据信息,但是又不想存储数据库表,那么可以考虑使用Cookie 技术。其实 JavaScript 也可以操作 Cookie。比如用户登录记录登录状态,就可以考虑使用Cookie。比如视频网站播放的时候,记录当前播放进度或者音量等等,也可以考虑使用 Cookie。
  • Session与Cookie的区别: Session存储数据在服务器端,Cookie在客户端;Session没有数据类型大小限制,Cookie有数据类型限制,仅限String类型,<=4KB;Session数据安全,Cookie相对于不安全。
    详情见原文

6、JSTL标签

1、什么是JSTL

  • JSP标准标识库,使用JSTL可实现JSP页面的逻辑处理; 可用于编写各种动态JSP页面
  • JSTL(Java server pages standarded tag library,即JSP标准标签库)是由JCP(Java community Proces)所制定的标准规范,它主要提供给JavaWeb开发人员一个标准通用的标签库,并由Apache的Jakarta小组来维护。
  • 开发人员可以利用JSTL标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。

2.JSTL环境搭建

导入jar包文件

jstl-x.x.jar

在jsp页面添加taglib指令

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  • 这里的uri 标识符指向jar包的tld文件,prefix为前缀,可以自定义,一般定义为c;也称为c标签

使用JSTL标签

  • 刚才用c作为前缀的,那么直接写<c:标签 , 标签属性>内容</c:标签> 即可

3、条件标签 —if

if标签的几个属性:

  • test:Boolean类型;决定是否处理标签体的内容,即条件判断
  • var:String类型;指定变量名,保存test属性的判断结果
  • scope:String类型;指定var值的作用域范围,默认为page,可选值:page,request,session,application

代码示例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用tablib指令指向jstl标签库,定义前缀名prefix--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--
在test中可写入条件判断(仅有test支持使用el标签),
var定义属性名,scope声明作用范围(默认为page,即PageContext域对象);
将该标签的test返回结果自动赋值给var,再由scope决定哪个域对象可以调用;--%>
<c:if test="${10<20}" var="qwe" scope="application">
    test判断为true:内容可显示!<br/>
</c:if>

scope指定了作用域,其他域对象获取不到==>
${pageScope.qwe}<br/>

上面指定的是application应用程序域对象==>
${qwe}
</body>
</html>

运行结果
在这里插入图片描述

4、迭代标签 —forEach

orEach对Java中的集合与数组进行遍历

forEach标签的几个属性:

  • (1)items : 获取需要迭代的集合或数组,支持EL表达式;类型为数组,字符串,集合;
  • (2)var : 定义一个变量,接收循环中获取的数据;不支持EL表达式,类型为String;
  • (3)varStatus : 获取循环的状态信息,不支持 EL表达式,类型为String;varStatus调用的几个参数:常用index,count
  • (4)step : 设置迭代的步长,默认为1; 支持EL表达式,类型为int;
  • (5)end : 设置迭代的结束索引 ,支持EL表达式,类型为int;若指定end属性,则在items的下标到指定end的位置就会结束迭代,若不指定,就全部迭代
  • (6)begin : 设置迭代的开始索引,支持EL表达式,类型为int;若指定begin属性,则从items的下标为begin的位置开始迭代,若不指定,则全部迭代

示例代码:

<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0, "张三");
    people.add(1, "李四");
    people.add(2, "王五");
    people.add(3, "赵六");
    people.add(4, "丁一");
    people.add(5, "胡二");
    request.setAttribute("list", people);
%>
<%--
var,每一次遍历出来的变量
items,要遍历的对象
begin, 开始位置
end,   结束位置
step, 步长
--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/>
    <br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
    <c:out value="${people}"/>
    <br>
</c:forEach>

7、EL表达式

1、EL表达式简介

  • EL表达式全称:Expression Language,即表达式语言
  • EL表达式作用:代替JSP页面中表达式脚本进行数据的输出
  • EL表达式比JSP的表达式脚本简洁很多
  • EL表达式的格式是:${表达式} ,注:EL表达式写在jsp页面中,表达式一般是域对象的key

2、EL表达式搜索域数据的顺序

  • EL表达式主要是输出域对象中的数据,当四个域对象都有同一个key的值时,EL表达式会按照四个域对象的范围从小到大进行搜索,找到就输出,与四个域对象声明的先后顺序无关
<body>
    <%							  
        //向四个域对象中都保存相同key的值
        request.setAttribute("key", "request");
        session.setAttribute("key", "session");
        application.setAttribute("key", "application");
        pageContext.setAttribute("key", "pageContext");
    %>
    <%--  使用EL表达式输出key的值  --%>
    ${key}
</body>

启动服务器,页面显示:

pageContext

3、EL表达式输出Java类的属性

session域内设置msgList在这里插入图片描述

<%--EL表达式根据key值msgList获取数据,然后进行遍历--%>
 <c:forEach items="${msgList}" var="msg"> 
                    <c:if test="${msg.state == 0}">
                        <li class="unReaded">
                    </c:if>
                    <c:if test="${msg.state == 1}">
                        <li >
                    </c:if>
                    <em>${msg.createDate}</em>
                    <em><a href="${pageContext.request.contextPath}/msg/returnMsg?id=${msg.id}">回信</a></em>
                    <em><a href="">删除</a></em>
                    <em>发送方:${msg.sender}</em>
                    <p>
                    <strong><a href="${pageContext.request.contextPath}/msg/readMsg?id=${msg.id}">${msg.title}</a></strong>
                    </p>
                </li>
                </c:forEach>

4、pageContext对象的使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%-- 先通过pageContext对象获取request、session对象,再获取以下内容 --%>
    <%--
        获取请求的协议:request.getScheme()
        获取请求的服务器ip或域名:request.getServerName()
        获取请求的服务器端口号:request.getServerPort()
        获取当前工程路径:request.getContextPath()
        获取请求的方式:request.getMethod()
        获取客户端的ip地址:request.getRemoteHost()
        获取会话的唯一标识:session.getId()
    --%>
1.协议: ${ pageContext.request.scheme }<br>
2.服务器ip:${ pageContext.request.serverName }<br>
3.服务器端口:${ pageContext.request.serverPort }<br>
4.获取工程路径:${ pageContext.request.contextPath }<br>
5.获取请求方法:${ pageContext.request.method }<br>
6.获取客户端ip地址:${ pageContext.request.remoteHost }<br>
7.获取会话的id编号:${ pageContext.session.id}<br>
</body>
</html>

运行结果:
在这里插入图片描述

5、param、paramValues对象的使用

<body>
    获取请求参数username的值:${ param.username } <br>
    获取请求参数password的值:${ param.password } <br>
    获取请求参数中第一个hobby的值:${ paramValues.hobby[0] } <br>
    获取请求参数中第二个hobby的值:${ paramValues.hobby[1] } <br>
    <%--  有多个同名的key时使用paramValues的索引值决定获取哪一个,使用param只可获取第一个  --%>
    使用param获取hobby的值:${ param.hobby } <br>
</body>

运行结果:
浏览器地址栏输入:http://localhost:8080/MyTest/Test.jsp?username=Jaychou&password=123&hobby=sing&hobby=dance
在这里插入图片描述

6、initParam对象的使用

在web.xml中写参数 (修改了web.xml中内容之后,需要重启服务才可生效):

<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql:///test</param-value>
</context-param>

test.jsp

<body>
    输出&lt;Context-param&gt;username的值:${ initParam.username } <br>
    输出&lt;Context-param&gt;url的值:${ initParam.url } <br>
</body>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值