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

来源:互联网 发布:sql server 版本查看 编辑:程序博客网 时间:2024/05/29 09:42

本示例是使用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

如有错误和纰漏请多多包含,欢迎在下面留言。

阅读全文
2 0