博客系统03 文章列表(上)

一、文章列表

(1)创建表

-- ----------------------------
-- Table structure for article
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
  `article_id` int(11) NOT NULL AUTO_INCREMENT,
  `article_title` varchar(100) DEFAULT NULL,
  `article_content` text,
  `article_time` int(11) DEFAULT NULL,
  `article_pic` varchar(100) DEFAULT NULL,
  `article_desc` varchar(255) DEFAULT NULL,
  `article_cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`article_id`),
  KEY `article_category` (`article_cid`),
  CONSTRAINT `article_category` FOREIGN KEY (`article_cid`) REFERENCES `category` (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

(2)建立domain

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class Article {
    private Integer article_id;
    private String article_title;
    private Integer article_time;
    private String article_content;
    private String article_pic;
    private String article_desc;
    private Category category;

    @Override
    public String toString() {
        return "Article{" +
                "article_id=" + article_id +
                ", article_title='" + article_title + '\'' +
                ", article_time=" + article_time +
                ", article_content='" + article_content + '\'' +
                ", article_pic='" + article_pic + '\'' +
                ", article_desc='" + article_desc + '\'' +
                ", category=" + category +
                '}';
    }
}

(3)建立关系映射

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.blog.domain.Article" table="article">
        <!--建立类属性哪一个是主键  还要跟数据库当中主键进行对象-->
        <id name="article_id" column="article_id">
            <generator class="native"/>
        </id>

        <!--建立类中的普通属性与数据库当中字段进行关联-->
        <property name="article_title" column="article_title"/>
        <property name="article_content" column="article_content"/>
        <property name="article_time" column="article_time"/>
        <property name="article_pic" column="article_pic"/>
        <property name="article_desc" column="article_desc"/>
        <many-to-one name="category" class="com.blog.domain.Category" column="article_cid"/>

    </class>
</hibernate-mapping>

hibernateApplication.xml 中添加映射文件

<!-- 设置映射文件 -->
<property name="mappingResources">
    <list>
        <value>com/blog/domain/User.hbm.xml</value>
        <value>com/blog/domain/Category.hbm.xml</value>
        <value>com/blog/domain/Article.hbm.xml</value>
    </list>
</property>

(4)查询文章列表数据

① 发送请求

<frameset rows="70,*" frameborder=0 border="0" framespacing="0">
    <frame src="mgr_top.jsp" name="topFrame" scrolling="NO" noresize>
    <frameset cols="250,*" frameborder="0" border="0"  framespacing="10">
        <frame src="mgr_left.jsp" name="leftFrame"  scrolling="NO">
        <frame src="${pageContext.request.contextPath}/article_list.action" name="mainFrame" >
    </frameset>
</frameset>

② 配置接收请求

web Action

import com.opensymphony.xwork2.ActionSupport;

public class ArticleAction extends ActionSupport {
    public String list(){
        System.out.println("来到action:list方法");
        return null;
    }
}

交给spring管理,applicationContext.xml

<!-- 文章action -->
<!-- action bean -->
<bean id="articleAction" class="com.blog.web.ArticleAction" scope="prototype">
</bean>

struts.xml配置,添加方法白名单

<!-- 文章action -->
<action name="article_*" class="articleAction" method="{1}">
    <allowed-methods>list</allowed-methods>
    <!--<allowed-methods>regex:.*</allowed-methods>-->
</action>

③ 调用业务层

ArticleService

import com.blog.domain.Article;
import java.util.List;

public interface ArticleService {
    /* 查询所有的文章业务 */
    List<Article>getAllArticle();
}

ArticleServiceImpl

import com.blog.Service.ArticleService;
import com.blog.domain.Article;
import java.util.List;

public class ArticleServiceImpl implements ArticleService {
    @Override
    public List<Article> getAllArticle() {
        System.out.println("来到Article业务层");
        return null;
    }
}

ArticleAction中注入并调用业务层

import com.blog.Service.ArticleService;
import com.blog.domain.Article;
import com.opensymphony.xwork2.ActionSupport;
import lombok.Setter;
import java.util.List;

public class ArticleAction extends ActionSupport {
    // 注入
    @Setter
    private ArticleService articleService;
    public String list(){
        System.out.println("来到action:list方法");
        // 调用业务层
        List<Article> allArticle = articleService.getAllArticle();
        return null;
    }
}

articleService 交给spring管理,applicationContext.xml

<!-- 文章action -->
<!-- action bean -->
<bean id="articleAction" class="com.blog.web.ArticleAction" scope="prototype">
    <property name="articleService" ref="articleService"/>
</bean>

<!-- service bean -->
<bean id="articleService" class="com.blog.Service.impl.ArticleServiceImpl">
</bean>

④ 调用dao层

ArticleDao

import com.blog.domain.Article;
import java.util.List;

public interface ArticleDao {
    List<Article>getAllArticle();
}

ArticleDaoImpl

import com.blog.dao.ArticleDao;
import com.blog.domain.Article;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import java.util.List;

public class ArticleDaoImpl extends HibernateDaoSupport implements ArticleDao {
    @Override
    public List<Article> getAllArticle() {
        System.out.println("来到ArticleDao");
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
        List<Article> list = (List<Article>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
        return list;
    }
}

ArticleServiceImpl中注入并调用dao层

import com.blog.Service.ArticleService;
import com.blog.dao.ArticleDao;
import com.blog.domain.Article;
import lombok.Setter;

import java.util.List;

public class ArticleServiceImpl implements ArticleService {
    // 注入
    @Setter
    private ArticleDao articleDao;
    @Override
    public List<Article> getAllArticle() {
        System.out.println("来到Article业务层");
        // 调用dao
        List<Article> allArticle = articleDao.getAllArticle();
        return allArticle;
    }
}

articleDao 交给spring管理,applicationContext.xml

<!-- 文章action -->
<!-- action bean -->
<bean id="articleAction" class="com.blog.web.ArticleAction" scope="prototype">
    <property name="articleService" ref="articleService"/>
</bean>

<!-- service bean -->
<bean id="articleService" class="com.blog.Service.impl.ArticleServiceImpl">
    <property name="articleDao" ref="articleDao"/>
</bean>

<!-- dao bean -->
<bean id="articleDao" class="com.blog.dao.impl.ArticleDaoImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

⑤ 解决 no-session 延迟加载问题

产生原因

关联对象默认都是采用延迟加载,事务都是在业务层开启和提交的,所以调用完业务层后,事务已经提交,session已经关闭了。

由于关联的对象延迟加载,当使用关联对象时,session已经不在了,所以会报no-session异常。

解决办法

(1)不使用延迟加载,但是效率太低,一般不使用。

(2)使用spring提供的解决方案OpenInViewFilter,spring提供了一个过滤器,在web视图层提供session的打开和关闭。在web.xml中配置(注意要加在struts过滤器之前)

<!--配置延迟加载-->
<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>*.action</url-pattern>
</filter-mapping>

(5)展示所有列表

① 把数据存取值栈当中,转发到 jsp

public String list(){
    System.out.println("来到action:list方法");
    // 调用业务层
    List<Article> allArticle = articleService.getAllArticle();
    System.out.println(allArticle);
    //把数据存取值栈当中,转发到jsp
    ActionContext.getContext().getValueStack().set("allArticle",allArticle);
    return "list";
}

② 配置结果页

<!-- 文章action -->
<action name="article_*" class="articleAction" method="{1}">
    <result name="list">/mgr_main.jsp</result>
    <allowed-methods>list</allowed-methods>
    <!--<allowed-methods>regex:.*</allowed-methods>-->
</action>

③ 展示所有列表

在 mgr_main.jsp 中

<%@ taglib uri="/struts-tags" prefix="s"%>

<s:iterator value="allArticle" var="article">
    <ul class="list_goods_ul">
        <li><s:property value="#article.article_id"/> </li>
        <li><s:property value="#article.article_title"/></li>
        <li><s:property value="#article.category.cname"/></li>
        <li>
            <a href="#">
                <img class="img_icon" src="${ctx }/images/edit_icon.png" alt=""></a>
        </li>
        <li>
            <a href="#">
                <img class="img_icon" src="${ctx }/images/delete_icon.png" alt="">
            </a>
        </li>
    </ul>
</s:iterator>

(6)分页展示文章

① 构建 pageBean

import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Setter@Getter
public class PageBean<T> {
    /*当前页*/
    private Integer currentPage;
    /*一页多少条数据*/
    private Integer pageSize;
    /*当前查询的角标*/
    private Integer index;
    /*总记录数*/
    private Integer totalCount;
    /*总页数*/
    private Integer totalPage;
    /*当前页的数据*/
    private List<T> list;
    
    /*如果当前页没有设置,默认设置为第1页*/
    public void setCurrentPage(Integer currentPage) {
        if (currentPage == null) {
            currentPage = 1;
        }
        this.currentPage = currentPage;
    }
    
    /*如果没有设置当前页总记录数据,设置默认记录数为一页5条*/
    public void setPageSize(Integer pageSize) {
        if (pageSize == null) {
            pageSize = 5;
        }
        this.pageSize = pageSize;
    }
    
    /*计算当前页从数据库当中查询的位置*/
    public Integer getIndex() {
        return (currentPage-1)*pageSize;
    }
    
    /*计算总页数*/
    public Integer getTotalPage() {
        double ceil = Math.ceil(totalCount * 1.0 / pageSize);
        return (int)ceil;
    }

    @Override
    public String toString() {
        return "PageBean{" +
                "currentPage=" + currentPage +
                ", pageSize=" + pageSize +
                ", index=" + index +
                ", totalCount=" + totalCount +
                ", totalPage=" + totalPage +
                ", list=" + list +
                '}';
    }
}

② 监听分页点击获取数据

//分页
$("#page").paging({
    pageNo:1,
    totalPage: 5,
    totalSize: 3,
    callback: function(num) {
        $(window).attr('location','/article_pageList.action?currPage='+num);
        // alert(num);
    }
});

mgr_left.jsp

<ul>
    <li><a href="${pageContext.request.contextPath}/category_list.action" target="mainFrame"><i></i>分类管理</a></li>
    <li><a href="${pageContext.request.contextPath}/article_pageList.action" target="mainFrame"><i></i>文章管理</a></li>
    <li></i><a href="mgr_account.jsp" target="mainFrame"><i></i>用户管理</a></li>
</ul>

mgr_index.jsp

<frameset rows="70,*" frameborder=0 border="0" framespacing="0">
    <frame src="mgr_top.jsp" name="topFrame" scrolling="NO" noresize>
    <frameset cols="250,*" frameborder="0" border="0"  framespacing="10">
        <frame src="mgr_left.jsp" name="leftFrame"  scrolling="NO">
        <frame src="${pageContext.request.contextPath}/article_pageList.action" name="mainFrame" >
    </frameset>
</frameset>

③ web层接收请求

/* 获取分页数据 */
@Setter
private Integer currPage = 1;
public String pageList(){
    System.out.println(currPage);
    DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
    //调用业务层
    PageBean pageBean = articleService.getPageData(detachedCriteria,currPage,5);
    //数据存到值栈当中
    ActionContext.getContext().getValueStack().push(pageBean);
    return "list";
}

方法白名单

<!-- 文章action -->
<action name="article_*" class="articleAction" method="{1}">
    <result name="list">/mgr_main.jsp</result>
    <allowed-methods>list,pageList</allowed-methods>
    <!--<allowed-methods>regex:.*</allowed-methods>-->
</action>

分页数据展示

<s:iterator value="list" var="article">
    <ul class="list_goods_ul">
        <li><s:property value="#article.article_id"/> </li>
        <li><s:property value="#article.article_title"/></li>
        <li><s:property value="#article.category.cname"/></li>
        <li>
            <a href="#">
                <img class="img_icon" src="${ctx }/images/edit_icon.png" alt=""></a>
        </li>
        <li>
            <a href="#">
                <img class="img_icon" src="${ctx }/images/delete_icon.png" alt="">
            </a>
        </li>
    </ul>
</s:iterator>
//分页
$("#page").paging({
    pageNo:<s:property value="currentPage"/>,
    totalPage: <s:property value="totalPage"/>,
    totalSize: <s:property value="totalCount"/>,
    callback: function(num) {
    $(window).attr('location','/article_pageList.action?currPage='+num);
    alert(num);
}
});

④ 服务层处理

在 ArticleServiceImpl 中实现getPageData()方法

@Override
public PageBean getPageData(DetachedCriteria detachedCriteria, Integer currPage, int pageSize) {
    PageBean<Article> pageBean = new PageBean<>();
    //设置当前页
    pageBean.setCurrentPage(currPage);
    //设置当前一页有多少条数据
    pageBean.setPageSize(pageSize);
    //获取总记录数
    //从数据库当中查询总记录
    Integer totalCount = articleDao.getTotalCount(detachedCriteria);
    pageBean.setTotalCount(totalCount);
    //设置总页数
    pageBean.setTotalPage(pageBean.getTotalPage());
    //设置数据当前页数据
    //查询数据库
    List<Article> list =  articleDao.getPageData(detachedCriteria,pageBean.getIndex(),pageBean.getPageSize());
    //计算
    pageBean.setList(list);
    System.out.println(pageBean);
    return pageBean;
}

⑤ dao层处理

@Override
public Integer getTotalCount(DetachedCriteria detachedCriteria) {
    //查询总记录
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = (List<Long>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
    if(list.size() > 0){
        return list.get(0).intValue();
    }
    return 0;
}

@Override
public List<Article> getPageData(DetachedCriteria detachedCriteria, Integer index, Integer
            pageSize) {

        //清空查询总记录条件
        detachedCriteria.setProjection(null);
        List<Article> list = (List<Article>)this.getHibernateTemplate().findByCriteria(detachedCriteria,
                        index, pageSize);
        return list;
    }
posted @ 2019-10-12 08:40  Lomen~  阅读(663)  评论(0编辑  收藏  举报