博客系统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;
}