您的位置:首页 > 编程语言 > Java开发

Java Web 图片管理与分享系统(Struts2+Hibernate+JSP实现)

2017-05-21 17:34 1111 查看


本示例是使用JavaWeb技术实现一个简单的图片管理与分享系统,其中主要功能如下:

用户分类浏览系统中的图片缩略图
用户查看单张图片的详细信息,图片下载
用户查看一个分类内的所有图片缩略图
用户使用关键字进行模糊搜索
管理员登录
管理员拥有普通用户的所有功能,同时能够实现图片的删除

使用的主要技术有: 

JavaEE、JSP、Struts2、Hibernate、JavaBean

本项目开发环境为:
Intellij IDEA 2016.3
Tomcat 8
JDK 1.8
MySQL 5.5

由于本人水平有限,该工程也只是我一边学习一边开发的一个用于课程作业的项目,所以其中还有很多不完善的地方,难免在某些情况下会有些bug,希望大家能够谅解。其实这个作业做了也过了快一个月了,很久没有更新博客了,所以今天这里记录下来,希望能够给其他同学一个参考和帮助,如果有什么建议或者问题也欢迎在博客下留言~

完整工程下载地址(包含网页截图和数据库建表sql文件):


http://download.csdn.net/detail/qq_24369113/9848301

简单的界面展示:

1.主页界面index.jsp:





2.图片详情页面item_preview.jsp:





3. 图片分类浏览页面AllcartoonPic.jsp/SearchResult.jsp:





4.图片上传界面contact.jsp:





为了方便大家建立数据库,这里也放上数据库的数据字典截图:



核心代码介绍:

对于主界面显示的index.jsp 主要就是调用Javabean(QueryAllPhoto)来从后台查询数据,然后返回一个ArrayList(person_pic_list),列表里面的每一个元素强制转换成一个PhotoInfoEntity对象之后,就可以取出每张图片的各种信息,主要代码片段如下:
其中index.jsp页面会有三个这种div,每一个div里显示八张该类别的图片的缩略图。其他的div里只是String category更换成相应的值就好了。
<div class="row">
<div class="col-xs-12 col-md-12">
<div class="item_container">
<% String category = "人物图片";
QueryAllPhoto query = new QueryAllPhoto();
ArrayList person_pic_list = query.QueryByExt(category);

%>
<%
for (int i = 0; i < 8 && i < person_pic_list.size(); i++) {
PhotoInfoEntity tem = (PhotoInfoEntity) person_pic_list.get(i);
%>
<!--一张图片的信息===============================================================================================================-->
<div class="item">
<a href="item_preview.jsp?id=<%=tem.getId()%>&dir=<%=tem.getDir()%>&ext=<%=tem.getExt()%>&realName=<%=tem.getRelName()%>&ip=<%=tem.getIp()%>&dt=<%=tem.getDt()%>&info=<%=tem.getInfo()%>"
class="thumbnail">
<img src="<%=tem.getDir()%>" alt="377 blue tech">
<p><%=tem.getRelName()%>
</p>
</a>
</div>
<%
}
%>

</div>
</div>
</div>



每个jsp页面的查询功能是由下面这一小段代码实现:
通过post 方法将keyword信息提交到SearchResult.jsp页面。
<form action="SearchResult.jsp" method="post" class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" class="form-control" name="keyword" id="keyword" placeholder="图片查询">
</div>
<button type="submit" class="btn btn-default">查询</button>
</form>


在SearchResult.jsp页面,使用String keyword = request.getParameter("keyword");得到需要查询的图片关键字信息,然后同样调用后台的JavaBean实现查询,并将结果返回到一个ArrayList中。然后和index.jsp一样将一张张的图片显示出来。
核心代码片段如下:
 <div class="row">
                    <div class="col-xs-12 col-md-12">
                        <div class="item_container">
                            <% String keyword = request.getParameter("keyword");
                                QueryAllPhoto query = new QueryAllPhoto();
                                ArrayList pic_list = query.QueryByKeyword(keyword);

                            %>

                            <%
                                if (pic_list.size() == 0) {
                            %>
                            <div class="item">
                                <p><b>查询不到相关的图片,请更换关键字再次尝试。</b></p>
                            </div>
                            <% } else {
                                for (int i = 0; i < pic_list.size(); i++) {
                                    PhotoInfoEntity tem = (PhotoInfoEntity) pic_list.get(i);
                            %>
                           <!-- 一张图片的信息======================================-->
                            <div class="item">
                               <a href="item_preview.jsp?id=<%=tem.getId()%>&dir=<%=tem.getDir()%>&ext=<%=tem.getExt()%>&realName=<%=tem.getRelName()%>&ip=<%=tem.getIp()%>&dt=<%=tem.getDt()%>&info=<%=tem.getInfo()%>"
                                   class="thumbnail">
                                    <img src="<%=tem.getDir()%>" alt="377 blue tech">
                                    <p><%=tem.getRelName()%>
                                    </p>
                                </a>
                            </div>

                            <%
                                    }
                                }
                            %>
                       </div>
                    </div>
</div>


在index.jsp界面点击一张图片的缩略图会自动跳转到该图片的详情页,实现思路是点击图片缩略图之后会自动跳转到item_preview.jsp页面,由于在URL中存储了图片的相关信息,所以在item_preview.jsp页面直接使用request.getparameter()方法就能够得到该图片的各种详细信息。然后在直接显示出来就行。
<a href="item_preview.jsp?id=<%=tem.getId()%>&dir=<%=tem.getDir()%>&ext=<%=tem.getExt()%>&realName=<%=tem.getRelName()%>&ip=<%=tem.getIp()%>&dt=<%=tem.getDt()%>&info=<%=tem.getInfo()%>"


实际上,我的这种实现方式并不科学,我这种相当于在index.jsp页面就已经把一张图片的各种信息都查询出来了,然后只是没有显示出来而已,然后在图片详情页再直接显示出来,这样的话其实在图片数量较多或图片较大的情况下,index.jsp页面的加载将会非常的缓慢。
较科学的实现方式是,在index.jsp页面只查询图片的标签信息、图片编号、图片的存储路径,然后在item_preview.jsp页面根据图片的编号信息再去查询一次数据库得到图片的完整详情。

前台的代码还有一个需要说明的地方就是管理员的登录,使用的是Struts2,框架来实现登录信息的处理的,主要代码片度如下:
form表单中使用post方式将表单信息提交到CheckLogin.action这个action来处理。Struts2框架会捕捉到这个请求并实例化相应的action类来进行相应的处理。
<form method="post" action="CheckLogin.action">
<div class="panel">
<div class="panel-head"><strong>管理员登录</strong></div>
<div class="panel-body" style="padding:30px;">
<div class="form-group">
<div class="field field-icon-right">
<input type="text" class="input" name="admin" placeholder="登录账号"  />
<span class="icon icon-user"></span>
</div>
</div>
<div class="form-group">
<div class="field field-icon-right">
<input type="password" class="input" name="password" placeholder="登录密码" />
<span class="icon icon-key"></span>
</div>
</div>

</div>
<div class="panel-foot text-center">
<button class="button button-block bg-main text-big">立即登录</button>
</div>
</div>
</form>


上传图片的contact.jsp也是使用Struts2框架来捕获上传的图片信息和请求,主要代码如下:
表单通过post方式将表单信息提交到UploadPic这个action进行处理。
<form role="form" enctype="multipart/form-data" method="post" action="UploadPic">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<input name="pic_name" type="text" class="form-control" id="pic_name" placeholder="图片名称">
</div>
<div class="form-group">
<select name="pic_ext" type="text" class="form-control" id="pic_ext" placeholder="图片类型">
<option>卡通图片</option>
<option>风景图片</option>
<option>人物图片</option>
</select>
</div>
<div class="form-group">
<input type="file" name="pic_data" id="pic_data" class="form-control"/>
</div>
</div>
<div class="col-md-7">
<div class="form-group">
<textarea name="pic_info" rows="6" class="form-control" id="pic_info" placeholder="图片描述信息..."></textarea><br>
<button type="submit" class="btn btn-primary">确认上传</button>
</div>
</div>
</div>
</form>


下面介绍Struts2的配置文件:
以第一个action为例,name属性是表示这个action的名称为UploadPic(也就是jsp中form表单里填写的那个),
class属性是指定执行该请求的实体类是cn.hncu.Action包下的UploadAction.java这个类,
method属性表示调用UploadAction.java这个类中的ajaxGetImage()这个方法来具体处理,
result标签表示如果ajaxGetImage()的返回值是字符串“Successful”那么就跳转到index.jsp,
如果ajaxGetImage()的返回值是字符串“failed”那么跳转到contact.jsp。

下面的两个action也是以此类推。
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

<package name="struts2" namespace="/" extends="struts-default">
<action name="UploadPic" class="cn.hncu.Action.UploadAction" method="ajaxGetImage">
<result name="successful">index.jsp</result>
<result name="failed">contact.jsp</result>
</action>

<action name="DeletePic" class="cn.hncu.Action.DeleteAction" method="DeleteImage">
<result name="successful">index.jsp</result>
<result name="failed">item_preview.jsp</result>
</action>

<action name="CheckLogin" class="cn.hncu.Action.CheckLoginAction" method="check">
<result name="successful">index.jsp</result>
<result name="failed">AdminLogin.jsp</result>
</action>
</package>
</struts>


接下来是要实现UPloadAction类和其中的方法:
Struts2框架会自动实例化一个UploadAction对象,然后将jsp表单中的属性使用setter和getter方法封装到这个对象的同名属性中,然后自动调用配置文件中指定的ajaxGetImage()方法。
package cn.hncu.Action;

import cn.hncu.Dao.PhotoInfoEntity;
import org.apache.struts2.ServletActionContext;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by 32706 on 2017/4/19.
*/
public class UploadAction {
private File pic_data;//Ajax获取图片文件,与控件type=File中的name属性一样
private String pic_name;//Ajax获取图片文件名称,相应的name属性名称+FileName
private String pic_ext;//图片类别
private String pic_info;//图片描述信息

/**
* -----------相应的get和set方法----------------
**/
public File getPic_data() {
return pic_data;
}

public void setPic_data(File pic_data) {
this.pic_data = pic_data;
}

public String getPic_name() {
return pic_name;
}

public void setPic_name(String pic_name) {
this.pic_name = pic_name;
}

public String getPic_ext() {
return pic_ext;
}

public void setPic_ext(String pic_ext) {
this.pic_ext = pic_ext;
}

public String getPic_info() {
return pic_info;
}

public void setPic_info(String pic_info) {
this.pic_info = pic_info;
}

/**
* 通过Ajax获取图片信息
*
* @return
* @throws IOException
*/
public String ajaxGetImage() throws Exception {

HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
if (pic_data != null) {
String fileName = pic_data.getName();
String savePath = ServletActionContext.getServletContext().getRealPath("/");

String finalPath = save_pic_on_disk(pic_data, savePath, fileName);
if (finalPath != null)//将图片存储到本地文件
{
if (upload_info_to_database(finalPath, pic_ext, pic_info, "administrator", pic_name))//调用hibernate将数据插入数据库
{
response.getWriter().print("图片上传成功!");//把相应的地址放到前台解析,通过#符号分割
return "successful";
} else {
System.out.println("调用hibernate持久化过程出错");
response.getWriter().print("图片上传失败!====调用hibernate持久化过程出错");
return "failed";
}
} else {
response.getWriter().print("图片上传失败!====保存到本地失败");
return "failed";
}

} else {
System.out.println("图片数据为空=====================");
response.getWriter().print("图片上传失败!");
return "failed";
}

}

private boolean upload_info_to_database(String savePath, String pic_ext, String info, String ip, String pic_name) {
try {
java.util.Date date = new java.util.Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss");
String time = format.format(date);//得到完成订单的时间
DateFormat format1 = new SimpleDateFormat("yyyyMMddHHmmss");
String pic_id = format1.format(date) + (int) (Math.random() * 1000);

Configuration conf = new Configuration().configure();
SessionFactory sf = conf.buildSessionFactory();
//Session session = sf.openSession();
Session  session=sf.getCurrentSession();
PhotoInfoEntity photo = new PhotoInfoEntity();
photo.setDir(savePath);
photo.setDt(time);
photo.setExt(pic_ext);
photo.setId(pic_id);
photo.setInfo(info);
photo.setIp(ip);
photo.setRelName(pic_name);

Transaction tran = session.beginTransaction();
session.save(photo);
tran.commit();
session.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

private String save_pic_on_disk(File data, String savePath, String fileName) {
String rt = "";
java.util.Date date = new java.util.Date();
DateFormat format = new SimpleDateFormat("yyyyMMdd");
String time = format.format(date);//得到完成订单的时间
System.out.println(savePath);
String dir_url = "uploadImage/" + time + "/";
String realFileName=new Date().getTime()+fileName+".jpg";
String realPath=savePath+dir_url+realFileName;

System.out.println("最终保存的文件路径为======" + realPath);

try {

File file = new File(savePath + dir_url);//每天的图片放在一个文件夹里
//如果文件夹不存在则创建
if (!file.exists() && !file.isDirectory()) {
System.out.println(dir_url + "文件夹不存在,新建一个");
file.mkdir();
}

FileOutputStream out=new FileOutputStream(realPath);
FileInputStream in=new FileInputStream(data);
byte[]buffer=new byte[1024];
int len=0;
while((len=in.read(buffer))!=-1){
out.write(buffer,0,len);

}
out.flush();
out.close();
in.close();
return dir_url+realFileName;

} catch (Exception e) {
e.printStackTrace();
System.out.println("保存文件到文件中出错=================Database.save_picture_in_file");
return null;
}
}
public static void main(String arg[]) {
}
}


另外两个Action的实现是类似的,这里限于版面就不在赘述了,大家可以下载完整的工程文件查看。(博客底部和顶部有下载链接)

介绍到这里还有一个前台使用的JavaBean没有介绍到,这个就是QueryAllphoto.java:
其中有两个方法,一个是QueryByExt()方法,表示根据图片的类别来查询,在图片分类浏览和index.jsp页面会使用到。
第二个方法是QueryByKeyword(),是使用图片标签的关键字来进行查询。

package cn.hncu.Dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;

import java.util.ArrayList;
import java.util.List;

public class QueryAllPhoto {

public  ArrayList QueryByExt(String category) {
ArrayList rt=new ArrayList();
Configuration configuration=new Configuration().configure();
SessionFactory sessionFactory=configuration.buildSessionFactory();
Session session=sessionFactory.openSession();

String hql="from PhotoInfoEntity where ext='"+category+"'";
System.out.println(hql+"========================================================================");

Query query=session.createQuery(hql);
List list=query.list();
for(int i=0;i<list.size();i++)
{
PhotoInfoEntity tem=(PhotoInfoEntity)list.get(i);
rt.add(tem);
}
System.out.println(rt.size()+"大小========================================================================");
return  rt;
}

public  ArrayList QueryByKeyword(String keyword) {
ArrayList rt=new ArrayList();
Configuration configuration=new Configuration().configure();
SessionFactory sessionFactory=configuration.buildSessionFactory();
Session session=sessionFactory.openSession();

String hql="from PhotoInfoEntity where relName  like '%"+keyword+"%'";
System.out.println(hql+"========================================================================");

Query query=session.createQuery(hql);
List list=query.list();
for(int i=0;i<list.size();i++)
{
PhotoInfoEntity tem=(PhotoInfoEntity)list.get(i);
rt.add(tem);
}
System.out.println(rt.size()+"大小========================================================================");
return  rt;
}

public  static  void main(String arg[])
{
QueryAllPhoto q=new QueryAllPhoto();
ArrayList result=q.QueryByExt("风景图片");

System.out.println(result.size());

}

}


在QueryAllPhoto.java中我们调用了Hibernate框架来实现数据的访问和查询等操作,下面就来介绍Hibernate的配置文件hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?>
<!--表明解析本XML文件的DTD文档位置,DTD是Document Type Definition 的缩写,即文档类型的定义,XML解析器使用DTD文档来检查XML文件的合法性。hibernate.sourceforge.net/hibernate-configuration-3.0dtd可以在Hibernate3.1.3软件包中的src\org\hibernate目录中找到此文件-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!--声明Hibernate配置文件的开始-->
<hibernate-configuration>
<!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的操作-->
<session-factory>
<!--配置数据库的驱动程序,Hibernate在连接数据库时,需要用到数据库的驱动程序-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机,    hibernate是数据库名-->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/photo</property>
<!--连接数据库是用户名-->
<property name="connection.username">root</property>
<!--连接数据库是密码-->
<property name="connection.password">root</property>
<!--数据库连接池的大小-->
<property name="hibernate.connection.pool.size">20</property>
<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率-->
<property name="hibernate.show_sql">true </property>
<!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。Fetch Size设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢-->
<property name="jdbc.fetch_size">50 </property>
<!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。Batch Size越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大-->
<property name="jdbc.batch_size">23 </property>
<!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->
<property name="jdbc.use_scrollable_resultset">false </property>
<!--connection.useUnicode连接数据库时是否使用Unicode编码-->
<property name="Connection.useUnicode">true </property>
<!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->
<property name="connection.characterEncoding">utf-8</property>

<!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect </property>
<mapping resource="cn/hncu/Dao/PhotoInfoEntity.hbm.xml"/>
<mapping class="cn.hncu.Dao.PhotoInfoEntity"/>
<mapping class="cn.hncu.Dao.AdminEntity"/>
<mapping resource="cn/hncu/Dao/AdminEntity.hbm.xml"/>

</session-factory>
</hibernate-configuration>


为了使Hibernate能够将数据库表和java对象联系起来,我们还需要两个持久化对象类:AdminEntity.java 以及PhotoInfoEntity.java
这两个类在intellij中是可以自动生成的,具体方法可以查看博文:http://blog.csdn.net/u014520745/article/details/51408049
在eclipse等 IDE中的生成方式请自行百度。
这里就简单介绍下AdminEntity.java:
该类中的每一个属性对应数据库表中的一个属性,然后每个属性会有一个setter和getter方法。
PhotoInfoEntity.java也是类似只是属性会多一些。

package cn.hncu.Dao;

import javax.persistence.*;

/**
* Created by 32706 on 2017/4/20.
*/
@Entity
@Table(name = "admin", schema = "photo", catalog = "")
public class AdminEntity {
private String adminName;
private String password;

@Id
@Column(name = "admin_name")
public String getAdminName() {
return adminName;
}

public void setAdminName(String adminName) {
this.adminName = adminName;
}

@Basic
@Column(name = "password")
public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

AdminEntity that = (AdminEntity) o;

if (adminName != null ? !adminName.equals(that.adminName) : that.adminName != null) return false;
if (password != null ? !password.equals(that.password) : that.password != null) return false;

return true;
}

@Override
public int hashCode() {
int result = adminName != null ? adminName.hashCode() : 0;
result = 31 * result + (password != null ? password.hashCode() : 0);
return result;
}
}


至此整个工程的一些主要核心代码就已经介绍完了,如果需要工程源文件请访问:
http://download.csdn.net/detail/qq_24369113/9848301

如有错误和纰漏请多多包含,欢迎在下面留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐