备案 控制台
开发者社区 数据库 文章 正文

【Web实战-Tomcat-Servlet-Thymeleaf -JDBC-MySQL】浏览器页面显示数据库数据(水果库存系统)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
推荐场景:
学生管理系统数据库设计 搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 了解浏览器页面显示数据库数据(水果库存系统)。

微信图片_20221031112727.png

前言


在JDBC专栏中,我们完成了水果库存系统功能的设计,实现以及优化,但总得来看,整个项目都是后端的代码,系统的页面也不过是通过控制台模拟而来的,而非真正的前端页面。


而在这篇文章开始,我们会对水果库存系统的客户端页面功能进行设计与实现,让库存系统可以在网页中使用。


项目中我们主要依赖Tomcat部署,使用Servlet组件,过程中通过JDBC连接MySQL数据库获取数据,将数据在浏览器页面中展现出来。


一、Thymeleaf - 视图模板技术


在开始,我们需要先了解一下Thymeleaf - 视图模板技术的使用,这是我们在使用Servlet时需要用到的技术。


接下来,我们通过 Thymeleaf 的使用来了解视图模板技术到底是什么。


1.导入 jar 包


需要使用Thymeleaf - 视图模板技术,第一步就是导入相关的 jar 包了,具体的步骤大家应该都了解,不了解的可以按照这篇文章的思路来尝试导入jar包:druid数据库连接池的使用。


Thymeleaf - 视图模板技术 jar包资源:

链接: https://pan.baidu.com/s/1NOucl2A8nEAIzg-rT4GqGg

提取码:leaf


2.创建Servlet类,设置相关属性与方法。


我们需要创建一个Servlet类,我将这个类命名为ViewBaseServlet,说其是Servlet类是因为它需要继承HttpServlet类。

ViewBaseServlet类中设置的是与使用Thymeleaf 技术相关的属性以及方法,我们可以通过代码来了解其功能:

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ViewBaseServlet extends HttpServlet {
    private TemplateEngine templateEngine;
    @Override
    public void init() throws ServletException {
        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");
        templateResolver.setPrefix(viewPrefix);
        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");
        templateResolver.setSuffix(viewSuffix);
        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);
        // ⑤设置是否缓存
        templateResolver.setCacheable(true);
        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");
        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();
        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);
    }
    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");
        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());
        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}


3.添加web.xml文件配置


web.xml文件是一个Web项目的配置文件.


上文提到的ViewBaseServlet类代码中,有两个重要的部分:


添加前缀 view-prefix

添加后缀 view-suffix

除了ViewBaseServlet类,我们还需要在web.xml文件中添加前缀与后缀相关的参数配置,参数配置代码如下:

<context-param>
        <param-name>view-prefix</param-name>
        <param-value>/</param-value>
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>

参数配置中,我们将前缀设置为/;同时后缀设置为.html。


这样的用意在于我们可以使用Thymeleaf - 视图模板技术,通过逻辑视图名称获取到对应的物理视图名称,例如:


//假设此时的视图名称是index

//那么Thymeleaf会将这个 逻辑视图名称 对应到 物理视图名称上去

//逻辑视图名称 : index

//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix

//所以真实的视图名称是 / + index + .html


我们先了解一下使用的效果即可,至于为什么这样,我们会在后续代码的实现中体现出来。


4.使用Thymeleaf技术相关的HTML标签属性


在HTML中,需要使用Thymeleaf技术,我们需要在html标签中添加相关属性:

<html xmlns:th="http://www.thymeleaf.org">
</html>

而后,当我们使用Thymeleaf技术的属性时,都需要在属性前添加th:的标志。


二、浏览器页面实现


1.获取数据库数据


我们需要在浏览器页面中显示数据库中存放的数据,那么我们就首先要连接数据库来获取数据,这时候正好就需要连接数据库执行更新或查询操作的功能。


相关功能的通用方法,已经在我们的JDBC专栏:JDBC实战系列文章中完成,直接拿过来使用即可:


BaseDAO类代码:

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
 * @author .29.
 * @create 2022-09-25 19:30
 */
public abstract class BaseDAO<T> {
    public final String DRIVER = "com.mysql.cj.jdbc.Driver";
    public final String URL = "jdbc:mysql://localhost:3306/fruitdb?useSSL=false&useUnicode=true&CharacterEncoding=utf-8";
    public final String USER = "root" ;
    public final String PSW = "" ;
    protected Connection connection;
    protected PreparedStatement pstm;
    protected ResultSet rs;
    //获取T的对象
    private Class entityClass;
    //构造方法
    public BaseDAO(){
        //getClass() 获取Class对象,我们当前创建的是FruitDAOImpl对象,new FruitDAOImpl();
        //那么子类的构造方法内部首先调用父类(BaseDAO)的空参构造器,
        //因此此处的getCalss()会被执行,但是获取的是子类FruitDAOImpl的Class
        //所以getGenericSuperclass()获取的是BaeDAO的class
        Type genericType = getClass().getGenericSuperclass();//获取泛型父类类型
        //强转成 ParameterizedType 参数化类型
        //getActualTypeArguments 获取实际的类型参数
        Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
        //只传入了一个参数,数组首位就是我们需要获取的<T>的真实类型
        Type actualType = actualTypeArguments[0];
        //actualType.getTypeName();获取类型名
        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //将加载驱动,连接数据库的操作包装成方法,减少代码复用率
    protected Connection conn(){
        try {
            //加载驱动
            Class.forName(DRIVER);
            //数据库管理器,连接数据库
            connection = DriverManager.getConnection(URL, USER, PSW);
            return connection;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //将关闭资源的操作包装成方法
    protected  void close(ResultSet rs,PreparedStatement pstm,Connection connection){
        try {
            if(rs != null)
                rs.close();
            if(pstm != null)
                pstm.close();
            if(connection != null)
                connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //执行更新,返回影响行数的方法(如果是插入操作,返回自增列主键值)
    protected int executeUpdate(String sql,Object... params){//... params不确定数量的参数
        boolean insertFlag = false;
        insertFlag = sql.trim().toUpperCase().startsWith("INSERT");
        try {
            connection = conn();
            //(sql语句不通用,靠参数传递进来)
            //sql语句
            //String sql = "update t_fruit set fcount = ? where fname like ?";
            //预处理对象
            if(insertFlag){
                pstm = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            }else{
                pstm = connection.prepareStatement(sql);
            }
            setParams(pstm,params);
            int count = pstm.executeUpdate();
            rs = pstm.getGeneratedKeys();
            if(rs.next()){
                return ((Long)rs.getLong(1)).intValue();
            }
            //参数填充也不通用,也靠参数传递进来
            if(params != null && params.length > 0){
                for(int i = 0;i < params.length;++i){
                    pstm.setObject(i+1,params[i]);
                }
            }
            return count;//执行更新,返回影响行数
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            close( rs, pstm, connection);
        }
        return 0;//影响行数为0
    }
    //通过反射技术,给obj对象的property属性赋propertyValue值
    protected void setValue(Object obj, String property,Object propertyValue){
        Class clazz = obj.getClass();
        try {
            //获取property这个字符串对应的属性名,比如fid去找obj对象中对应的fid属性值
            Field field = clazz.getDeclaredField(property);
            if(field != null){
                field.setAccessible(true);//强制访问(即使private属性也能访问),防止属性为private
                field.set(obj,propertyValue);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    //执行复杂查询,返回... 例如统计结果
    protected Object[] executeComplexQuery(String sql,Object... params){
        try {
            //加载驱动,连接数据库的方法
            connection = conn();
            //预处理对象
            pstm = connection.prepareStatement(sql);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据:描述结果集信息的数据(有哪些列,什么类型。。。)
            ResultSetMetaData rsmd = rs.getMetaData();
            //获取元数据列数
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            if(rs.next()){
                for(int i = 0;i < columnCount;++i){
                    Object columValue = rs.getObject(i + 1);
                    columnValueArr[i] = columValue;
                }
                return columnValueArr;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            close( rs, pstm, connection);
        }
        return null;
    }
    //执行查询,返回单个实体对象
    protected T load(String sql,Object... params){
        try {
            //加载驱动,连接数据库的方法
            connection = conn();
            //预处理对象
            pstm = connection.prepareStatement(sql);
            setParams(pstm,params);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据:描述结果集信息的数据(有哪些列,什么类型。。。)
            ResultSetMetaData rsmd = rs.getMetaData();
            //获取元数据列数
            int columnCount = rsmd.getColumnCount();
            if(rs.next()){
                T entity = (T) entityClass.newInstance();
                for(int i = 0;i < columnCount;++i){
                    String columnName = rsmd.getColumnName(i + 1);
                    Object columValue = rs.getObject(i + 1);
                    setValue(entity,columnName,columValue);
                }
                return entity;
            }
        } catch (SQ
        LException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally{
            close( rs, pstm, connection);
        }
        return null;
    }
    //给预处理参数设置参数
    protected void setParams(PreparedStatement psmt,Object... params) throws SQLException {
        if(params != null && params.length > 0 ){
            for(int i = 0;i < params.length;++i){
                psmt.setObject(i+1,params[i]);
            }
        }
    }
    // 执行查询,返回结果集并输出
    protected List<T> executeQuery(String sql,Object... params){
        List<T> list = new ArrayList<>();
        try {
            //加载驱动,连接数据库的方法
            connection = conn();
            //预处理对象
            pstm = connection.prepareStatement(sql);
            setParams(pstm,params);
            //执行查询,返回结果集
            rs = pstm.executeQuery();
            //通过rs可以获取结果集的元数据
            //元数据:描述结果集信息的数据(有哪些列,什么类型。。。)
            ResultSetMetaData rsmd = rs.getMetaData();
            //获取元数据列数
            int columnCount = rsmd.getColumnCount();
            while(rs.next()){
                T entity = (T) entityClass.newInstance();
                for(int i = 0;i < columnCount;++i){
                    String columnName = rsmd.getColumnName(i + 1);
                    Object columValue = rs.getObject(i + 1);
                    setValue(entity,columnName,columValue);
                }
                list.add(entity);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally{
            close( rs, pstm, connection);
        }
        return list;
    }
}

这时候,我们还需要有一个方法来调用BaseDAO类中的通用方法,从而完成查询数据的需求,在这里我们依旧创建一个FruitDAO接口,并创建其实现类FruitDAOImpl类来重写方法,完成功能。


FruitDAO接口:

我们需要在浏览器页面中显示数据库的数据,就需要一个获取数据库所有信息的方法。

import com.haojin.fruit.pojo.Fruit;
import java.util.List;
/**
 * @author .29.
 * @create 2022-10-04 16:39
 */
public interface FruitDAO {
    //获取所有的库存信息
    List<Fruit> getFruitList();
}

FruitDAOImpl类:

实现类中调用了BaseDAO类中查询数据的通用方法,将SQL语句传入,将获取到的数据存入集合中返回。

import com.haojin.fruit.pojo.Fruit;
import com.haojin.myssm.basedao.BaseDAO;
import java.util.List;
/**
 * @author .29.
 * @create 2022-10-04 16:39
 */
public class FruitDAOImpl extends BaseDAO<Fruit> implements FruitDAO{
    @Override
    public List<Fruit> getFruitList() {
        return super.executeQuery("SELECT * FROM t_fruit");
    }
}


2.使用Servlet组件渲染页面


当我们打开对应的浏览器页面,就会向客户端中的Servlet组件发起一次请求,我们这时候将获取到的数据库数据保存到session保存作用域中,然后在HTML文件中进行渲染,之后将页面响应给客户端的浏览器中,如此一来就在浏览器中显示出数据库数据。


①Servlet组件

import com.haojin.fruit.pojo.Fruit;
import com.haojin.fruit.pojo.dao.FruitDAO;
import com.haojin.fruit.pojo.dao.FruitDAOImpl;
import com.haojin.myssm.basedao.myspringmvc.ViewBaseServlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
/**
 * @author .29.
 * @create 2022-10-04 16:42
 */
//Servlet从3.0版本开始,支持注解方式的注册
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList();
        //保存到session作用域
        HttpSession session = request.getSession();
        session.setAttribute("fruitList",fruitList);
        //此处的视图名称是index
        //那么Thymeleaf会将这个 逻辑视图名称 对应到 物理视图名称上去
        //逻辑视图名称 : index
        //物理视图名称 : view-prefix   +    逻辑视图名称    +    view-suffix
        //所以真实的视图名称是  /        +       index      +      .html
          super.processTemplate("index",request,response);
    }
}

②HTML页面


这是我们水果库存系统的浏览器页面代码,在页面中我们会设置一个标题以及一个表格,表格中展示的就是我们数据库中保存的水果库存数据。


因为我们获取到的数据是一个集合,所以在HTML文件中需要用到 Thymeleaf 技术的标签属性:


th:if

th:unless

th:each

th:text

循环遍历上文保存在session保存作用域中的数据,如果数据为空,显示库存危机为空:

<tr th:if="${#lists.isEmpty(session.fruitList)}">
  <td colspan = 4>对不起,库存为空!</td>
</tr>


如果保存的数据不为空,获取数据中每一行数据的信息(水果,价格,库存),第四列的删除标志后续功能完善后可以通过点击实现删除操作。

<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit:${session.fruitList}">
  <td th:text="${fruit.fname}"></td>
  <td th:text="${fruit.price}"></td>
  <td th:text="${fruit.fcount}"></td>
  <td><img src="del.jpg" width="24px"/></td>
    </tr>

完整html代码:

<html xmlns:th="http://www.thymeleaf.org">
 <head>
  <meta charset="UTF-8">
  <style type = "text/css">
  </style>
<link rel = "stylesheet" href = "index.css">
 </head>
 <body>
  <div id = "div_container">
  <div id = "list">
  <p class="center f30">欢迎使用水果库存后台系统</p>
  <table id = "tbl">
  <tr>
  <th class = "w20">名称</th>
  <th class = "w20">单价</th>
  <th class = "w20">库存</th>
  <th>操作</th>
    </tr><br/>
  <tr th:if="${#lists.isEmpty(session.fruitList)}">
  <td colspan = 4>对不起,库存为空!</td>
  </tr>
  <tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit:${session.fruitList}">
  <td th:text="${fruit.fname}"></td>
  <td th:text="${fruit.price}"></td>
  <td th:text="${fruit.fcount}"></td>
  <td><img src="del.jpg" width="24px"/></td>
    </tr>
  </table>
  </div>
  </div>
 </body>
</html>

css效果代码:

#div_container{
               width:80%;
      height:100%;
               border:1px solid white;
      margin-left:10%;
      float:left;
      }
#list{
      width:100%;
      border:0px solid white;
      }
#tbl , #tbl tr,#tbl th,#tbl td{
  border:1px solid gray;
  text-align:center;
}
#tbl{
  margin-top:120px;
  margin-left:20%;
  width:60%;
}
.w20{
  width:20%;
}
.center{
  text-align: center;
}
.f30{
  font-size: 30px;
}
body{
  padding:0;
  margin:0;
  background-color:aquamarine;
}
div{
  position:relative;
  float:left;
}
.input{
       border:1px solid lightgray;
    width:90%;
}


三、效果

微信图片_20221031114229.png


总结


这篇文章中,我们将获取到的数据库数据渲染到了浏览器页面上,当然这只不过是开始,我们的水果库存系统还有许多功能没有渲染到页面中,比如新增库存的功能、修改库存的内容、删除指定水果信息的功能、页面的分页功能等。


我将在后续的文章中为客户端页面增添上述提到的内容,逐步完善系统,在完善系统项目的同时,掌握好相关的知识。


微信图片_20221031114236.png

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
.29.
目录
相关文章
老板这功能得加钱
|
1月前
|
Android开发
Android WindowFeature小探究,Android客户端Web页面通用性能优化实践
Android WindowFeature小探究,Android客户端Web页面通用性能优化实践
老板这功能得加钱
21 0
小白学大数据
|
3天前
|
XML 前端开发 数据挖掘
Web数据提取:Python中BeautifulSoup与htmltab的结合使用
Web数据提取:Python中BeautifulSoup与htmltab的结合使用
小白学大数据
11 1
花开富贵111
|
3天前
|
关系型数据库 MySQL API
实时计算 Flink版操作报错合集之同步MySQL数据到另一个MySQL数据库,第一次同步后源表数据发生变化时目标表没有相应更新,且Web UI中看不到运行的任务,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
花开富贵111
58 0
JavaPub
|
7天前
jetty内嵌web页面服务入门
jetty内嵌web页面服务入门
JavaPub
7 1
opencv学堂
|
13天前
|
XML JavaScript 前端开发
基于SVG的web页面图形绘制API介绍
基于SVG的web页面图形绘制API介绍
opencv学堂
20 4
日_升
|
14天前
|
Web App开发 JavaScript 前端开发
Web 页面性能衡量指标-以用户为中心的性能指标
Web 页面性能衡量指标-以用户为中心的性能指标 以用户为中心的性能指标是理解和改进站点体验的关键点 一、以用户为中心的性能指标 1. 指标是用来干啥的? 指标是用来衡量性能和用户体验的 2. 指标类型 • 感知加载速度:网页可以多快地加载网页中的所有视觉元素并将其渲染到屏幕上 • 加载响应速度:页面加载和执行组件快速响应用户互动所需的 JavaScript 代码的速度 • 运行时响应速度:网页在加载后对用户互动的响应速度 • 视觉稳定性:页面上的元素是否会以用户意想不到的方式发生偏移,是否可能会干扰用户的互动? • 流畅性:过渡和动画是否以一致的帧速率渲染,并在一种状态之间流畅地流动
日_升
19 1
全全.
|
23天前
|
存储 数据采集 JavaScript
基于Python的Web数据与解析
基于Python的Web数据与解析
全全.
35 0
caramel
|
24天前
|
DataWorks 安全 数据可视化
手把手操作-在自建的 Web 嵌入 DataWorks 数据血缘图
DataWorks 提供丰富的数据可视化界面,让用户能轻松地透过界面操作大数据业务,但仍有集成至自建 Web 界面的需求,减少切换页面的频率。下文就以透过阿里云令牌服务结合自建 Web 界面代理登录阿里云,做到嵌入DataWorks数据地图的血缘图。
caramel
67 1
手把手操作-在自建的 Web 嵌入 DataWorks 数据血缘图
嘟嘟嘟嘟嘟嘟
|
28天前
|
Kubernetes Oracle 关系型数据库
实时计算 Flink版产品使用合集之web ui能否在线管理数据source和处理数据
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
嘟嘟嘟嘟嘟嘟
22 0
芯在这
|
1月前
|
Java 数据库连接 数据库
实时计算 Flink版操作报错合集之flink jdbc写入数据时,长时间没写入后报错,是什么原因导致的
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
芯在这
48 9

热门文章

最新文章

  • 1
    Serverless 应用引擎产品使用之在阿里函数计算中,使数据库和阿里云函数计算位于同一个内网中如何解决
  • 2
    手把手教你实现 OceanBase 数据到阿里云数据库 SelectDB 内核版 Apache Doris 的便捷迁移|实用指南
  • 3
    数据库库表结构设计:原理、实例与最佳实践
  • 4
    数据管理DMS操作报错合集之阿里云DMS控制台上展示出了已经删除的数据库信息,如何解决
  • 5
    云原生数据仓库产品使用合集之ADB如何确保数据库的可用性
  • 6
    开源向量数据库比较:Chroma, Milvus, Faiss,Weaviate
  • 7
    【MySQL】数据库规范化的三大法则 — 一探范式设计原则
  • 8
    【Go语言专栏】使用Go语言连接MySQL数据库
  • 9
    【PHP 开发专栏】PHP 连接 MySQL 数据库的方法
  • 10
    存储系统、数据库和对象存储 | 青训营
  • 1
    解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
    736
  • 2
    Tomcat AJP连接器配置secretRequired=“true“,但是属性secret确实空或者空字符串,这样的组合是无效的。
    184
  • 3
    打破Tomcat中的双亲委派机制:探讨与实践
    105
  • 4
    tomcat核心技术+Nginx性能调优技术
    69
  • 5
    Tomcat的源码剖析, 启动过程你会吗?
    12
  • 6
    互联网大厂为什么禁止SpringBoot项目使用Tomcat?
    72
  • 7
    tomcat8绑定两个https域名
    24
  • 8
    优化tomcat的性能
    26
  • 9
    玩转Apache Tomcat
    32
  • 10
    Tomcat安装shell脚本
    39
  • 相关课程

    更多
  • MySQL企业常见架构与调优经验分享
  • 云数据库MySQL版快速上手教程
  • 阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
  • MySQL实战进阶
  • 数据库及SQL/MySQL基础
  • 云数据库MySQL快速入门
  • 相关电子书

    更多
  • WEB浏览器中即将发生的安全变化
  • 基于浏览器的实时构建探索之路
  • 基于浏览器的实时构建探索之路--玄寂
  • 相关实验场景

    更多
  • 测试场景(RDS无优惠)
  • MySQL引擎及架构优化
  • 基于EBS部署高性能的MySQL服务
  • 使用Python完成RDS数据开发及分析
  • Excel文件转存到RDS数据库
  • 使用CloudLens采集RDS日志并进行审计分析
  • 推荐镜像

    更多
  • mysql
  • mariadb
  • postgresql
  • 下一篇
    基于函数计算模板部署AI应用实践

    PHP网站源码民治关键词按天扣费民治企业网站制作同乐建网站布吉网站开发惠州如何制作网站龙华关键词排名包年推广南山网站推广系统深圳网络广告推广西乡网站搭建民治百姓网标王平湖关键词排名爱联优秀网站设计大运网站改版南山建网站石岩网站优化排名吉祥网站优化推广塘坑网络营销沙井模板网站建设罗湖企业网站改版丹竹头网站排名优化深圳建站光明百度爱采购双龙企业网站制作广州网站推广方案盐田网络广告推广坂田模板网站建设大鹏网站推广方案福田百度网站优化永湖阿里店铺运营广州建网站歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

    PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化