SpringMVC从本地磁盘读取图片显示到JSP页面上

上一篇博客是从数据库中读取图片的二进制信息流然后显示到JSP页面上,下面是将图片存储到我的本地磁盘E中,然后在数据库中只存图片的名字
将磁盘的路径写到配置文件中,从配置文件中将地址读取出来,图片显示的流程与前一篇博客的一样,只不过图片存储的地方不一样。

下面来展示我的实现流程.

(1)数据库中只保存图片的id和名字,我用的是oracle数据库,id是自增的,至于如何建表实现id自增等,我已经有博客介绍过这个,这里我展示下我自己写了一个工具类用来建表.

<span style="font-family:Comic Sans MS;">public class CreTableUtil {
	/**
	 * 
	 * @param tableName
	 * 创建表
	 */
	public void create(String tableName,JdbcTemplate jdbcTemplate){
		jdbcTemplate.execute("create table "+tableName+"(photo_id int,photo_data blob,photo_name varchar2(100),primary key(photo_id))");
	}
	/**
	 * 
	 * @param seq
	 * 创建序列
	 */
	public void createSequence(String seq,JdbcTemplate jdbcTemplate){
		String create_seq="create sequence "+seq +" start with 1 "
				+ "increment by 1 minvalue 1 maxvalue 999999 nocycle nocache";
		jdbcTemplate.execute(create_seq);
	}
	/**
	 * 为id设置自增
	 */
	
	public void idIncrement(String tablename,String seq,JdbcTemplate jdbcTemplate){
		String sql="insert into "+ tablename+"(photo_id) values("+seq+".NEXTVAL)";
		jdbcTemplate.execute(sql);
	}
	/**
	 * 创建触发器
	 */
	public void create_trigger(String tablename,String seq,String triggerName,JdbcTemplate jdbcTemplate){
		String creat_trig="create  trigger "+triggerName+" before insert on "+tablename+" for each row begin select "+seq+".NEXTVAL into :new.photo_id from dual;end;";
		jdbcTemplate.execute(creat_trig);
	}
	
}</span>

2)使用mybatis的generatorConfig.xml自动生成DAO类,至于生成过程我在之前也已经介绍过了。
      最后生成的 PhotoModel类如下:

<span style="font-family:Comic Sans MS;">public class PhotoModel {
    private BigDecimal id;
    private String name;
    public BigDecimal getId() {
        return id;
    }
    public void setId(BigDecimal id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}</span>

PhotoModelDAO如下:

<span style="font-family:Comic Sans MS;">public interface PhotoModelDAO {
    int deleteByPrimaryKey(BigDecimal id);

    int insert(PhotoModel record);

    int insertSelective(PhotoModel record);

    PhotoModel selectByPrimaryKey(BigDecimal id);

    int updateByPrimaryKeySelective(PhotoModel record);

    int updateByPrimaryKey(PhotoModel record);
}</span>

自己创建的Service接口 :IPhotoModelService

<span style="font-family:Comic Sans MS;">public interface IPhotoModelService {
	int insert(String pName);
	public PhotoModel getPhotoById(BigDecimal photoId);
}</span>

Service实现类如下:

<span style="font-family:Comic Sans MS;">@Service("photoModelService")
public class PhotoModelServiceImpl implements IPhotoModelService{

	@Resource
	PhotoModelDAO photoModelDAO;
	public int insert(String pName) {
		PhotoModel pm=new PhotoModel();
		pm.setName(pName);
		return photoModelDAO.insert(pm);
	}

	public PhotoModel getPhotoById(BigDecimal photoId) {
		return photoModelDAO.selectByPrimaryKey(photoId);
	}
}</span>

(3)将图片输出到JSP页面上和将数据库读出出来的信息转换成json字符串传递到前台

<span style="font-family:Comic Sans MS;">@Controller
@Configuration
@ImportResource("classpath:spring.xml")
@RequestMapping("/showPicture")
public class PhotoModelController extends HttpServlet{
	 private static final long serialVersionUID=95163763702302821L;
	 @Value("${picUrl}")
	 private  String picUrl;
	 @Resource
	 private IPhotoModelService photoModelService;
	 
	 @RequestMapping("/toPicShow")
	 public String toPicShow(){
		 return "waterfullPic";
	 }
	 
	 
	 //根据请求的路径中的参数id,从本地磁盘中读取图片,picUrl是从配置文件中读取出来的
	 @RequestMapping("/tofindPic")
	 public void picToJSP(@PathParam("id")int id,HttpServletRequest request,HttpServletResponse response){
		 PhotoModel photoModel=photoModelService.getPhotoById(new BigDecimal(id));
		 String photoName=photoModel.getName();
		 FileInputStream in;
		 response.setContentType("application/octet-stream;charset=UTF-8");
		 try {
			 //图片读取路径
			//in=new FileInputStream("E:\\picture\\"+photoName);
			<strong><span style="color:#cc0000;">in=new FileInputStream(picUrl+photoName);</span></strong>
			int i=in.available();
			byte[]data=new byte[i];
			in.read(data);
			in.close();
			
			//写图片
			OutputStream outputStream=new BufferedOutputStream(response.getOutputStream());
			outputStream.write(data);
			outputStream.flush();
			outputStream.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
	 }
	 
	//从数据库中读取信息转换成json格式传递到前台
     @RequestMapping("/picToJsonReturn.do")
     @ResponseBody
     public String picToJsonReturn(HttpServletRequest request,Model model){
    	 System.out.println("aaaaa");
    	 JSONArray jsonArray=new JSONArray();
 		for(int i=10;i<31;i++){
 			PhotoModel p=photoModelService.getPhotoById(new BigDecimal(i));
 			jsonArray.add(p);
 		}
 		return jsonArray.toString();
     }
}
</span>

(4)前台页面显示图片

<span style="font-family:Comic Sans MS;"><body>
<div id="main">
		<div class="pin">
			<div class="box">
			 <!-- 通过从数据库中读出图片的二进制信息流显示图片的Controller处理路径 -->
			 <!--  <img src="/Login_ssm_mav_picbyte/user/toLookImage?id=13">  --> <!-- 注意这里的访问路径是正确的是,之前因为在web.xml文件中写成了png,所以折腾了很久 -->
			<!-- 通过从本地E盘读取图片显示图片 -->
			<img src="/Login_ssm_mav_picbyte/showPicture/tofindPic?id=10">
			</div>
		</div>
		<div class="pin">
			<div class="box">
			  <!-- <img src='/Login_ssm_mav_picbyte/static/pic/img2.jpg'> -->
			  <img src="/Login_ssm_mav_picbyte/showPicture/tofindPic?id=11">
			</div>
		</div>
		<div class="pin">
			<div class="box">
			  <img src="/Login_ssm_mav_picbyte/showPicture/tofindPic?id=12">
			</div>
		</div>
		<div class="pin">
			<div class="box">
			  <img src="/Login_ssm_mav_picbyte/showPicture/tofindPic?id=13">
			</div>
		</div>
		<div class="pin">
			<div class="box">
			  <img src="/Login_ssm_mav_picbyte/showPicture/tofindPic?id=14">
			</div>
		</div>
	</div>
</body></span>


waterfull.js代码如下:

<span style="font-family:Comic Sans MS;">window.οnlοad=function(){/*当页面加载的时候调用函数*/
   setInterval(function(){window.onscroll   = sscroll();},1000);
	waterfall('main','pin');
	
	window.οnscrοll=sscroll();
}
/*之前将函数写在里面时一直实现不了,现在这样写在外面便可以了。*/

function sscroll(){
	var pic;//原来要把变量定义在这里,之前定义在外面,就会出现undefined的错误
	$.ajax({
		async:false,
		type:'get',//get是获取数据,post是带数据的向服务器发送请求
		//url:'addAction.do',
		url:'picToJsonReturn.do',
		dataType:'json',
		success:function(data){
			pic=eval(data);//转换成js对象
		},
		error:function(data){
			alert("JSON数据获取失败,请联系管理员!");
		}
	});
	
	
	var dataInt={'data':[{'src':'img1.jpg'},{'src':'img2.jpg'},{'src':'img3.jpg'},{'src':'img4.jpg'},{'src':'img5.jpg'},{'src':'img6.jpg'}]};
	if(checkscrollside()){
			var oParent=document.getElementById('main');
			for(var i=0;i<pic.length;i++){
				var oPin=document.createElement('div');//添加元素节点
				oPin.className='pin';
				oParent.appendChild(oPin);
				var oBox=document.createElement('div');
				oBox.className='box';
				oPin.appendChild(oBox);
				var oImg=document.createElement('img');
				//oImg.src='/Login_ssm_mav_picbyte/static/pic/'+dataInt.data[i].src;
				//oImg.src=src='/Login_ssm_mav_picbyte/user/toLookImage?id='+pic[i].photoId;
				oImg.src=src='/Login_ssm_mav_picbyte/showPicture/tofindPic?id='+pic[i].id;
				//oImg.src='http://localhost:9988/pic/'+pic[i].photoName;
				oBox.appendChild(oImg);
			}
			waterfall('main','pin');
}
}
function waterfall(parent,pin){

    var oParent=document.getElementById(parent);//父级对象
    var aPin=getClassObj(oParent,pin);//获取存储pin的数组的pin
    var iPinW=aPin[0].offsetWidth;//一个块框pin的宽
    var num=Math.floor(document.documentElement.clientWidth/iPinW);//每行中能容纳的pin的个数[窗口的宽度除以一个块框的宽度]
    oParent.style.cssText='width:'+iPinW*num+'px;margin:0 auto;';//设置父级居中样式:定宽+自动水平外边距

     var pinHArr=[];//用于存储没列中的所有块框相加的高度
     for(var i=0;i<aPin.length;i++){
     	var pinH=aPin[i].offsetHeight;
     	if(i<num){
     		pinHArr[i]=pinH;//第一行中的num个块框pin先添加进数组pinHrr
     	}else{
     		var minH=Math.min.apply(null,pinHArr);//数组pinHArr中的最小值
     		var minHIndex=getminHIndex(pinHArr,minH);//获取高度最小的pin的index
     		aPin[i].style.position='absolute';//设置绝对偏移
     	    aPin[i].style.top=minH+'px';
     	    aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';
            pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加了快框后的列高
     	}
     }
}   

//获取高度最小的pin 的index
function getminHIndex(arr,minH){
	for(var i in arr){
		if(arr[i]==minH){
			return i;
		}
	}
}

/*通过父级和子元素的class名称获取该同类子元素的数组*/
function getClassObj(parent,className){
	var obj=parent.getElementsByTagName('*');//获取父类元素的所有子元素
	var pinS=[];//创建一个数组,用于收集子元素
	for(var i=0;i<obj.length;i++){//遍历子元素,判断类别,压入数组
		if(obj[i].className==className){
			pinS.push(obj[i]);
		}
	}
	return pinS;
}

function checkscrollside(){
	var oParent=document.getElementById('main');
	var aPin=getClassObj(oParent,'pin');
	var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);
	//创建【触发添加块框的的函数waterfall()】的高度:最后一个块框的与网页顶部的距离+自身高的一半(未滚到底便开始加载)
    
    //网页中获取滚动条卷去部分的高度
    var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
    var documentH=document.documentElement.clientHeight;//页面高度
    return (lastPinH<scrollTop+documentH)?true:false;//到达指定高度后返回true,触发waterfall()函数
}</span>

到这里我的瀑布墙图片展示基本算是完成了,不知道还有没有更好的处理图片的方法。


版权声明:本文为cwzhsi原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。