搞完2个J2EE项目后,现在回到学校,见经常有人问如何来处理J2EE中对图片的DB存取,今天借学校的这个有点名气的论坛.略微发表下我对这中问题的解决看法.希望大家踊跃顶贴.
基本的就不说了,这里直接进入正题,由于图片的binary码很大,往往在存数据库的时候都会采用java.sql.Blob类型,这是技术规范下统一的观点,而具体操作需要借助于java.IO(Input/Output)技术来实现.
首先:建立好数据表 user,字段为: id(varchar 32,primaryKey),username(varchar 20),photo(blob)
2. 在Spring Ioc容器中配置Hibernate以及对它的声明式事物代理 spring.cfg.xml
<?xml version encoding="GBK" ?>
<!DOCTYPE beans
PUBLIC -//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-bean.dtd">
<beans>
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://192.168.1.100:3306/mydbms</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>***</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="datasource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>user.hbm.xml</value>
</list>
</property>
</bean>
<bean id="userDAO" clas="test.userDAO">
<property name="sessionFactory">
<ref local="sessionfactory"/>
</property>
</bean>
<bean id="tansactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!--配制代理-->
<bean id="user" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="tansactionManager"/>
</property>
<property name="target">
<ref local="userDAO"/>
</proeprty>
<property name="proxyTargetClass" value="true"/>
<property name="transactionAttributes">
<props>
<prop key="set*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="delete*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="update*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
</beans>
3.定义Hibernate映射文件 user.hbm.xml
<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-dtd-3.0.dtd">
<hibernate-mapping>
<class name="test.user" table="user">
<id name="id" unsaved-value="false">
<generator class="uuid.hex"/>
</id>
<property name="username" type="string" column="username"/>
<property name="photo" type="blob" column="photo"/>
</class>
</hibernate-mapping>
4.编写实体Bean user.java
package test;
public class user implements java.io.Serializable{
private String id,username;
private java.sql.Blob photo;
public void setId(String id){
this.id=id;
}
public String getId(){
return this.id;
}
public void setUsername(String username){
return this.username;
}
public String getUsername(){
return this.username;
}
public void setPhoto(java.sql.Blob photo){
this.photo=photo;
}
public java.sql.Blob getPhoto(){
return this.photo;
}
}
5 编写DAO层 userDao.java
package test;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
public class userDao extends HibernateDaoSupport{
private static Logger log=Logger.getLogger(userDao.class);
static{
BasicConfigurator.configure();
}
public void setUser(user user){
getHibernateTemplate().save(user);
}
public void updateUser(user user){
getHibernateTemplate().update(user);
}
public void deleteUser(user user){
getHibernateTemplate().delete(user);
}
public user getUserByPrimaryKey(String id){
return getHibernateTemplate().get(user.class,id);
}
public java.util.List getAllUsers(){
return getHibernateTemplate().find("from user");
}
}
6.编写添加照片的用户注册JSP页: registry.jsp
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uti="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html:html lang="true">
<html:base />
<head><head>
<body>
<html:form action="/registry" method="post">
UserName:<html:text property="username"/>
Photo:<html:file property="photo"/>
<html:submit value="registry"/>
</html:form>
</body>
</html:html">
7.编写显示图片的页 view.jsp
<@% taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html:html>
<body>
<img src="http://192.168.1.100:8080/test/servlet/photo?user=<c:out value="${user}"/>">
</body>
</html:html>
8.实现Struts MVC
8.1: 注册实现: ActionForm
package test.mvc;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class registryForm extends ActionForm{
private String id,username,photo;
//省略对属性的setter and getter
}
registryAction.java
package test.mvc;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
public class registryAction extends Action{
public ActionForward execute(ActionMapping mapp,ActionForm form,HttpServletRequest req,HttpServletResponse res)throws Exception{
WebApplicationContext context=WebApplicationContextUtils.getRequiredWebApplicationContext(this.servlet.getServletContext());
registryForm Form=(registryForm)form;
java.io.FileInputStream is=new java.io.FileInputStream(new java.io.File(Form.getPhoto()));
java.sql.Blob blob=org.hibernate.Hibernate.createBlob(is);
userDao dao=(userDao)context.getBean("user");
user user=new user();
user.setUsername(Form.getUsername());
user.setPhoto(blob);
dao.setUser(user);
req.setAttribute("user",user); //把VO对象传递给下一站
return mapp.findForward("registryOK");
}
}
8.编写处理相片的servlet photo.java
package test.support;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import java.io.InputStream;
import java.io.IOException
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
public class photo extends HttpServlet{
private static Logger log=Logger.getLogger(photo.class);
static{
BasicConfigurator.configure();
}
public void init(ServletConfig config)throws ServletException{
super.init(config);
}
public void service(HttpServletRequest req,HttpServletResponse res)throws ServletException,IOExceotion{
res.reset();
res.setContentType("image/jpeg");
ServletOutputStream sop=res.getOutputStream();
if(req.getParameter("user")==null){
log.error("could not find Object user !");
return;
}
user user=(user)req.getParameter("user");
InputStream is=user.getPhoto().getBinaryStream();
byte[] bts=new byte[is.available()];
sop.write(bts);
}
}
Struts.cfg.xml这里稍微懂点Struts框架的人都会配置,我就懒得多写了,逻辑流程是:
regisry.jsp------------------>registryAction--------------------->view.jsp
这样只要注册了registry页,将会自动来到view.jsp.同时在view.jsp显示注册时的图片,只要传给photo这个servlet的参数user对象是持久对象.就能打出它的图片出来,本架构设计的有点粗糙,没有实现高层抽象,但相对弹性还是蛮大的,主要核心组件(photo.java和Action之间并不依赖.)
这里有个最重要的问题就是: servlet的response只能做一种方式的响应,换句话说就是用了PrintWriter后就不能用ServletOutputStream,否则它就要抗议了,它俩之间任意选一种,注意区别,Printwriter是打印流,用来把信息输到控制台,而ServletOutputStream则是用来传输数据,在实际中要根据他们的不同功能做出不同的选择.
这2天发了几个帖子,怎么不见人顶??