【JAVA秒会技术之搞定BLOB数据类型】如何读取及展示数据库中BLOB类型的图片

简介: 如何读取及展示数据库中BLOB类型的图片    【前言】最近在做某一需求时,需要从Oracle数据库读取图片。本以为数据库存储的会是一个简单的url,前台可以直接展示,结果却发现是BLOB二进制类型,于是乎,百度/Google了关键字“二进制图片读取及展示”,发现有很多“抄来抄去”的文章或博客,但是文章的质量都很低,而且结构比较混乱,看完之后仍然是“不明所以”。     最后,花了近2

如何读取及展示数据库中BLOB类型的图片

   【前言】最近在做某一需求时,需要从Oracle数据库读取图片。本以为数据库存储的会是一个简单的url,前台可以直接展示,结果却发现是BLOB二进制类型,于是乎,百度/Google了关键字“二进制图片读取及展示”,发现有很多“抄来抄去”的文章或博客,但是文章的质量都很低,而且结构比较混乱,看完之后仍然是“不明所以”。

    最后,花了近2个小时,耐心研究了一下,终于成功。于是总结如下,供大家参考,也作为自己积累备份所用!

      【核心点

       1.在PO类中用byte[]类型直接接受BLOB类型;

       2.将二进制转为Base64格式字符串(不要用sun.misc.BASE64Encoder类);

       3.前台html页面通过<img src="data:image/png;base64,{图片字段}"/>标签展示。

        1.需求概述

        ①从Oracle数据库的表中读取BLOB类型图片;

        ②在前端页面将图片展示出来。

        2.创建PO类,PO类中用byte[]类型直接接受BLOB类型 

package com.netease.numen.plus.netease.model;
import java.io.Serializable;
/**
 * 读取二进制blob类型图片
 * <p>Title: PhotoBytes</p>
 * @author  Liyan
 * @date    2017年3月6日 下午5:02:22
 */
public class PhotoBytes implements Serializable {
	private static final long serialVersionUID = -8775612234303127935L;
	/**二进制图片*/
	private byte[] photoBytes;
	public byte[] getPhotoBytes() {
		return photoBytes;
	}
	public void setPhotoBytes(byte[] photoBytes) {
		this.photoBytes = photoBytes;
	}	
}

        3.编写Mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.**.netease.mapper.WorkCardMapper">

	<resultMap id="photoBytes" type="com.**.netease.model.PhotoBytes">
		<result column="PHOTO" property="photoBytes" />
	</resultMap>

	<!-- 根据员工工号查询照片 -->
	<select id="getPhoto" resultMap="photoBytes">
		SELECT
			PHOTO as photoBytes
		FROM
			EHRINBOUND.EHR_EMPLOYEE_PHOTO_V
		<where>
			<if test="jobNumber!=null">
				AND EHR_EMPLOYEE_CODE = #{jobNumber} 
			</if>
		</where>
	</select>
	
</mapper>

        4.编写Mapper.java文件

@Repository
public interface WorkCardMapper {
	public PhotoBytes getPhoto(Map<String, Object> param) throws Exception;
}

        5.编写Service.java文件

public interface WorkCardService {	
	public PhotoBytes getPhoto(final String jobNumber) throws Exception;
}

        6.编写ServiceImpl.java文件

@Service("workCardService")
public class WorkCardServiceImpl implements WorkCardService{
	@Inject
	WorkCardMapper mapper;
	@Override
	public  PhotoBytes getPhoto(String jobNumber) throws Exception {
        Map<String, Object> param = new HashMap<String, Object>(0);
	    param.put("jobNumber", jobNumber);
	}
}

        7.编写二进制流转Base64字符串的工具类

package com.netease.numen.plus.netease.util;
import java.io.IOException;
import org.apache.commons.codec.binary.Base64;
public class Base64ImageUtil {
	/**
	 * 二进制流转Base64字符串
	 * <p>Title: byteArr2String</p>
	 * @author Liyan
	 * @date   2017年3月6日 下午3:04:47
	 * @param data
	 * @return String
	 * @throws IOException    
	 */
	public static String byteArr2String(byte[] byteArr) throws Exception {
		String stringBase64 = null;		
		try {
			 Base64 encoder = new Base64();
			 stringBase64 =(byteArr != null ? encoder.encodeToString(byteArr) : "");
		} catch (Exception e) {
			throw new Exception("byteArr2String转换异常:"+e);
		}
		return stringBase64;
    }
}

      【引申:为什么不要使用sun.misc.BASE64Encoder类?

      很多人在使用Base64进行加密解密时,都是使用sun.misc包下的BASE64Encoder及BASE64Decoder。但是,可能会出现这样的状况:换了JDK后发现提示找不到该类!

      网上有办法说重新配置jre就行了。但事实上不是这么简单的,这是要看配置的jre的类型是execution environment(执行环境),还是alternate jre(替代jre)。

      这两种方法中,如果是第一种就不行,因为是执行环境,也就是不会含JDK的一些额外类,rt.jar中的很多包都会因为jre与jdk权限不同而导致被限定权限,其中就包含了sun包。

     如果是第二种方法,即JDK替代jre,这就没问题,因为使用的是jdk的权限,所以不会报这类的错误。

     但是,事实上,这两个方法都是sun公司的内部方法,并没有在java api中公开过,所以使用这些方法是不安全的,将来随时可能会从中去除,所以应该使用相应的替代对象及方法!【参考:http://fableking.iteye.com/blog/1426410】

       8.编写Controller.java文件

   以下为简写,主要步骤是将byte[]型转Base64的字符串,并返回给前端。实际还需要加上参数校验,异常处理,记录日志等逻辑。

package com.netease.numen.plus.netease.controller;
@Controller
@RequestMapping(value = "/workcard")
public class WorkCardController {
	@Inject
	WorkCardService service;
	
	@RequestMapping(value = "/getWorkCardInfo" )
	public String getWorkCardInfo(String jobNumber) {
		//根据员工工号,获取照片(byte[]类型)	
		PhotoBytes photoBytes = service.getPhoto(jobNumber);
		byte[] photoBytes2 = photoBytes.getPhotoBytes();
		//将二进制转为Base64格式字符串
		String photo64 = Base64ImageUtil.byteArr2String(photoBytes2);
		result = new ResultInf(200, "获取照片信息成功", photo64);
		SpringMvcUtil.renderJson(response, result);
		return null;
	}
}

       9.前台html页面展示

<img src="data:image/png;base64,{photo}"/>


 

相关文章
|
10天前
|
XML Java 数据库连接
性能提升秘籍:如何高效使用Java连接池管理数据库连接
在Java应用中,数据库连接管理至关重要。随着访问量增加,频繁创建和关闭连接会影响性能。为此,Java连接池技术应运而生,如HikariCP。本文通过代码示例介绍如何引入HikariCP依赖、配置连接池参数及使用连接池高效管理数据库连接,提升系统性能。
35 5
|
16天前
|
JSON 前端开发 JavaScript
java-ajax技术详解!!!
本文介绍了Ajax技术及其工作原理,包括其核心XMLHttpRequest对象的属性和方法。Ajax通过异步通信技术,实现在不重新加载整个页面的情况下更新部分网页内容。文章还详细描述了使用原生JavaScript实现Ajax的基本步骤,以及利用jQuery简化Ajax操作的方法。最后,介绍了JSON作为轻量级数据交换格式在Ajax应用中的使用,包括Java中JSON与对象的相互转换。
32 1
|
22天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
37 3
|
22天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
40 2
|
22天前
|
Java 数据库连接 数据库
深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能
在Java应用开发中,数据库操作常成为性能瓶颈。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能。文章介绍了连接池的优势、选择和使用方法,以及优化配置的技巧。
22 1
|
6月前
|
SQL Java 数据库连接
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
|
6月前
|
存储 设计模式 算法
Java从入门到精通:2.1.1深入学习Java核心技术——掌握Java集合框架
Java从入门到精通:2.1.1深入学习Java核心技术——掌握Java集合框架
|
6月前
|
算法 Java 程序员
论文翻译 | 【深入挖掘Java技术】「底层原理专题」深入分析一下并发编程之父Doug Lea的纽约州立大学的ForkJoin框架的本质和原理
本文深入探讨了一个Java框架的设计、实现及其性能。该框架遵循并行编程的理念,通过递归方式将问题分解为多个子任务,并利用工作窃取技术进行并行处理。所有子任务完成后,其结果被整合以形成完整的并行程序。 在总体设计上,该框架借鉴了Cilk工作窃取框架的核心理念。其核心技术主要聚焦于高效的任务队列构建和管理,以及工作线程的管理。经过实际性能测试,我们发现大多数程序的并行加速效果显著,但仍有优化空间,未来可能需要进一步研究改进方案。
83 3
论文翻译 | 【深入挖掘Java技术】「底层原理专题」深入分析一下并发编程之父Doug Lea的纽约州立大学的ForkJoin框架的本质和原理
|
6月前
|
XML Java 测试技术
【Java技术专题】「核心技术提升」最流行的Java模拟框架Mockito入门指南(Java单元测试)
【Java技术专题】「核心技术提升」最流行的Java模拟框架Mockito入门指南(Java单元测试)
81 0
|
6月前
|
Java 测试技术 API
【Java技术深入解析】「核心技术提升」最流行的Java模拟框架Mockito入门指南(Java单元测试)
还在使用 Mockito 1.x?看看 Mockito 2 有哪些新功能!Mockito 3 没有引入任何破坏性的 API 变动,但现在需要 Java 8 而不是 Mockito 2 的 Java 6。 Mockito 4 删除了过时的 API。Mockito 5 将默认 mockmaker 改为 mockito-inline,现在需要 Java 11。一次只支持一个主要版本,而且不会向旧版本回传更改内容。
144 0
【Java技术深入解析】「核心技术提升」最流行的Java模拟框架Mockito入门指南(Java单元测试)