SSH项目实战 之 博客系统

目录

博客系统

登录业务逻辑

web层

public String login(){
        //登录业务逻辑
        User resUser = loginService.login(user);
        if (resUser == null){
            //错误信息回显
            this.addActionError("用户名或密码错");
            //结果页跳转
            return LOGIN;
        }else {
            //保存用户信息
            ActionContext.getContext().getSession().put("curUser",resUser);
            return SUCCESS;
        }
    }

注入service

<bean id="loginAction" class="com.le.web.LoginAction" scope="prototype">
        <property name="loginService" ref="loginService"/>
</bean>

配置结果页

<action name="loginAciton_*" class="loginAction" method="{1}">
	<result name="success">/WEB-INF/mgr/mgr_index.jsp</result>
	<result name="login_out" type="redirect">/mgr_login.jsp</result>
	<allowed-methods>login,loginout</allowed-methods>
</action>

页面结果显示

登录成功展示用户

<%@ taglib uri="/struts-tags" prefix="s"%>
<div class="h_top_right">
	<span style="margin-right: 50px"><s:property value="#session.curUser.username"/></span>
	<span>
		<a href="${pageContext.request.contextPath}/loginAciton_loginout.action" style="color:lightseagreen" target="_parent">退出</a>
	</span>
</div>

登录失败错误信息展示

<%@ taglib uri="/struts-tags" prefix="s"%>
<div class="login">博客后台管理系统
	<span style="color:red"><s:actionerror/></span>
</div>

service层

@Transactional
public class LoginServiceImpl implements LoginService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public User login(User user) {
        //调用dao 查询 用户
        User resUser = userDao.getUser(user.getUsername(), user.getPassword());
        return resUser;
    }
}

注入dao

<bean id="loginService" class="com.le.service.impl.LoginServiceImpl">
	<property name="userDao" ref="userDao"/>
</bean>

dao层

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

    @Override
    public User getUser(String username, String password) {
        //到数据库当中查询
        //设置到哪个表当中去查
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
        //设置条件
        detachedCriteria.add(Restrictions.eq("username",username));
        detachedCriteria.add(Restrictions.eq("password",password));

        List<User> list = (List<User>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
        System.out.println(list);
        if (list.size()>0){
            return list.get(0);
        }
        return null;
    }
}

建立对应domain,与映射文件并引入

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

注入sessionFactory

<bean id="userDao" class="com.le.dao.impl.UserDaoImpl">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

退出业务逻辑

点击退出按钮

<span>
	<a href="${pageContext.request.contextPath}/loginAciton_loginout.action" style="color:lightseagreen" target="_parent">退出</a>
</span>

处理action业务逻辑

struts.xml

<action name="loginAciton_*" class="loginAction" method="{1}">
	<result name="success">/WEB-INF/mgr/mgr_index.jsp</result>
	<result name="login_out" type="redirect">/mgr_login.jsp</result>
	<allowed-methods>login,loginout</allowed-methods>
</action>

LoginAction类

public String loginout(){
	/*清空当前的用户session*/
	ActionContext.getContext().getSession().remove("curUser");
	return "login_out";
}

分类

添加

页面按钮点击

<div class="item1" >
    <div>
        <span>parentid:</span>
        <input type="text" class="am-form-field" id="parentid" >&nbsp;&nbsp;
        <br/>
        <span>分类名称:</span>
        <input type="text" class="am-form-field" id="cname" >&nbsp;&nbsp;
        <br/>
        <button class="am-btn am-btn-default" type="button" id="addcategory">添加</button>
    </div>
</div>

/*监听添加按钮点击*/
$("#addcategory").click(function () {
	/*获取文本框的内容*/
	var parentid = $("#parentid").val();
	var cname = $("#cname").val();
	alert(parentid+cname);
	/*发送请求*/
	$(window).attr('location','${pageContext.request.contextPath}/category_add.action?parentid='+parentid+'&cname='+cname);
});

web层接收请求

public class CategoryAction extends ActionSupport implements ModelDriven<Category> {
    private Category category = new Category();
    @Override
    public Category getModel() {
        return category;
    }

    //注入service
    @Setter
    private CategoryService categoryService;
    /*添加分类*/
    public String add(){
        //调用业务层
        categoryService.save(category);
        return "listAction";
    }
}		
配置struts2路径
<!--分类 action-->
<action name="category_*" class="categoryAction" method="{1}">
	<result name="list">/WEB-INF/mgr/mgr_category.jsp</result>
	<result name="listAction" type="redirectAction">category_list.action</result>
	<allowed-methods>add,list,updateUI,update,delete</allowed-methods>
</action>

注入service

<bean  id="categoryAction" class="com.le.web.CategoryAction" scope="prototype">
	<property name="categoryService" ref="categoryService"/>
</bean>

处理业务

@Transactional
public class CategoryServiceImpl implements CategoryService {
    @Setter
    private CategoryDao categoryDao;
    @Override
    public void save(Category category) {
        /*调用dao*/
        System.out.println("调用service");
        categoryDao.save(category);
    }
}

注入dao

<bean id="categoryService" class="com.le.service.impl.CategoryServiceImpl">
	<property name="categoryDao" ref="categoryDao"/>
</bean>

dao添加

public class CategoryDaoImpl extends HibernateDaoSupport implements CategoryDao {
    /*保存分类*/
    @Override
    public void save(Category category) {
        this.getHibernateTemplate().save(category);
    }
}    

注入工厂

<bean id="categoryDao" class="com.le.dao.impl.CategoryDaoImpl">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

查询所有

左侧分类链接点击发送请求

<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="${pageContext.request.contextPath}/location_account.action" target="mainFrame"><i></i>用户管理</a></li>
</ul>

配置接收请求

<!--分类 action-->
<action name="category_*" class="categoryAction" method="{1}">
	<result name="list">/WEB-INF/mgr/mgr_category.jsp</result>
	<result name="listAction" type="redirectAction">category_list.action</result>
	<allowed-methods>add,list,updateUI,update,delete</allowed-methods>
</action>

<bean  id="categoryAction" class="com.le.web.CategoryAction" scope="prototype">
	<property name="categoryService" ref="categoryService"/>
</bean>

action处理

    public String list(){
        //调用业务层 查询所有分类
        List<Category> list =  categoryService.getAllCategory();
        System.out.println(list);
        //把数据存到值栈当中
		ActionContext.getContext().getValueStack().set("categorylist",list);
        return "list";
    }
页面展示数据

<ul class="title_ul">
	<li>parentid</li>
	<li>分类名称</li>
	<li>修改分类</li>
	<li>删除分类</li>
</ul>
<s:iterator value="categorylist" var="category">
	<ul class="list_goods_ul">
		<li><s:property value="#category.parentid"/> </li>
		<li><s:property value="#category.cname"/></li>
		<li>
			<a href="#" class="updatebtn" data-id="<s:property value="#category.cid"/>">
				 <img class="img_icon" src="../../images/edit_icon.png" alt="">
			 </a>
		</li>
		<li>
			<a href="${pageContext.request.contextPath}/category_delete.action?cid=<s:property value="#category.cid"/>">
				<img class="img_icon" src="../../images/delete_icon.png" alt="">
			 </a>
		</li>
	</ul>
</s:iterator>

调用业务层

@Transactional
public class CategoryServiceImpl implements CategoryService {
    @Setter
    private CategoryDao categoryDao;
    @Override
    public void save(Category category) {
        /*调用dao*/
        categoryDao.save(category);
    }

    @Override
    public List<Category> getAllCategory() {
        //调用dao层查询所有分类
        List<Category> list = categoryDao.getAllCategory();
        return list;
    }
}

调用dao层

public class CategoryDaoImpl extends HibernateDaoSupport implements CategoryDao {
    /*保存分类*/
    @Override
    public void save(Category category) {
        this.getHibernateTemplate().save(category);
    }
    /*获取所有分类信息*/
    @Override
    public List<Category> getAllCategory() {
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Category.class);
        List<Category> list = (List<Category>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
        return list;
    }
}

修改

界面准备
结构
<div id="modal_content2" style="height: 250px; display: none">
	<div id="close2"><img src="images/delete_icon.png" alt=""></div>
	<div class="edit_content">

		<div class="item1">
			<div>
				<span>添加分类:</span>
			</div>
		</div>
		<div class="item1" >
			<div>
				<span>parentid:</span>
				<input type="text" class="am-form-field" id="parentid2" >&nbsp;&nbsp;
				<br/>
				<span>分类名称:</span>
				<input type="text" class="am-form-field" id="cname2" >&nbsp;&nbsp;
				<br/>
				<input type="hidden" id="cid2">
				<button class="am-btn am-btn-default" type="button" id="updatebtn">修改</button>
			</div>
		</div>
	</div>
</div>
样式
<style>
	#modal_content2{
		padding: 30px 20px;
		width: 400px;
		height: 200px;
		background: white;
		position: fixed;
		left: 50%;
		top: 50%;
		margin-left: -200px;
		margin-top: -100px;
		display: none;
	}
	#close2{
		position: absolute;
		right: 10px;
		top: 10px;
	}
</style>
监听修改按钮
<li>
    <a href="#" class="updatebtn" data-id="<s:property value="#category.cid"/>">
        <img class="img_icon" src="../../images/edit_icon.png" alt="">
    </a>
</li>

异步发送请求
/*监听修改按钮点击*/
$(".updatebtn").click(function () {
	/*1.当前点的是哪一条数据*/
	var cid = $(this).data("id");
	  /*取出对应id的数据,到数据库当中查询当前记录
	   * 返回给页面
	   * 展示到页面当中.
	   * 发送请求的时候,不需要页面的跳转 Ajax(前端技术)   能够取当前返回数据  展示到界面
	   * */
        $.post("${pageContext.request.contextPath}/category_updateUI.action",{"cid":cid},function (data) {
                console.log("-------json------");
                console.log(data);
                /*把json数据展示到文本框 */
                $("#parentid2").val(data[0].parentid);
                $("#cname2").val(data[0].cname);
                $("#cid2").val(data[0].cid);
        },"json");

	/*2.把修改界面弹出*/
	$("#modal_view").fadeIn();
	$("#modal_content2").fadeIn();
});

服务器接收请求;web层接收到数据后,以json形式返回;页面接收到返回的json进行展示

/*修改数据展示*/
public String updateUI() throws IOException {
	//调用业务层
	Category category2 = categoryService.getOneCategory(category.getCid());
	//把数据给页面
	//以json(数据格式) 响应给页面
	JSONArray jsonArray = JSONArray.fromObject(category2, new JsonConfig());
	//响应给页面
	ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
	ServletActionContext.getResponse().getWriter().println(jsonArray.toString());
	return null;
}

调用服务层

@Override
public Category getOneCategory(Integer cid) {
	//调用dao层
	return categoryDao.getOneCategory(cid);
}

调用dao层
@Override
public Category getOneCategory(Integer cid) {
	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Category.class);
	//设置条件
	detachedCriteria.add(Restrictions.eq("cid",cid));
	List<Category> list = (List<Category>)this.getHibernateTemplate().findByCriteria(detachedCriteria);
	if(list.size() > 0){
		return list.get(0);
	}
	return null;
}

修改按钮点击处理

<div class="item1" >
	<div>
		<span>parentid:</span>
		<input type="text" class="am-form-field" id="parentid2" >&nbsp;&nbsp;
		<br/>
		<span>分类名称:</span>
		<input type="text" class="am-form-field" id="cname2" >&nbsp;&nbsp;
		<br/>
		<input type="hidden" id="cid2">
		<button class="am-btn am-btn-default" type="button" id="updatebtn">修改</button>
	</div>
</div>
监听修改按钮
$("#updatebtn").click(function () {
	/*1.获取文本框值*/
	var parentid2 = $("#parentid2").val();
	var cname2 = $("#cname2").val();
	var cid2 = $("#cid2").val();
	/*2.发送请求*/
	$(window).attr('location','${pageContext.request.contextPath}/category_update.action?parentid='+parentid2+'&cname='+cname2+'&cid='+cid2);
});

修改web层业务处理
public String update(){
	//调用业务层
	categoryService.update(category);
	return "listAction";
}
跳转回列表页面
<!--分类 action-->
<action name="category_*" class="categoryAction" method="{1}">
	<result name="list">/WEB-INF/mgr/mgr_category.jsp</result>
	<result name="listAction" type="redirectAction">category_list.action</result>
	<allowed-methods>add,list,updateUI,update,delete</allowed-methods>
</action>

业务层

@Override
public void update(Category category) {
	//调用dao
	categoryDao.update(category);
}
dao层
@Override
public void update(Category category) {
	this.getHibernateTemplate().update(category);
}

删除

监听删除按钮点击

<li>
	<a href="${pageContext.request.contextPath}/category_delete.action?cid=<s:property value="#category.cid"/>">
		<img class="img_icon" src="../../images/delete_icon.png" alt="">
	 </a>
</li>
web接收
public String delete(){
	categoryService.delete(category);
	return "listAction";
}
业务层处理
@Override
public void delete(Category category) {
	categoryDao.delete(category);
}
dao层处理
@Override
public void delete(Category category) {
	this.getHibernateTemplate().delete(category);
}
转发到列表页
<!--分类 action-->
<action name="category_*" class="categoryAction" method="{1}">
	<result name="list">/WEB-INF/mgr/mgr_category.jsp</result>
	<result name="listAction" type="redirectAction">category_list.action</result>
	<allowed-methods>add,list,updateUI,update,delete</allowed-methods>
</action>

同步请求与异常请求

同步请求
  • 发送请求时,后面的标签都会等待请求结束(可能会出现后面标签空白,没有加载出来的暂时现象)
  • 请求结束后,后续标签才会继续加载
异步请求
  • 会另开一条线单独去发送请求
  • 后续标签会继续加载.
  • 请求完毕后, 会通知请求结束.

文章列表

创建表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for article
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article`  (
  `article_id` int(11) NOT NULL AUTO_INCREMENT,
  `article_title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `article_time` bigint(11) NULL DEFAULT NULL,
  `article_content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `article_pic` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `article_desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `article_cid` int(255) NULL DEFAULT NULL,
  PRIMARY KEY (`article_id`) USING BTREE,
  INDEX `fk_article_category`(`article_cid`) USING BTREE,
  CONSTRAINT `fk_article_category` FOREIGN KEY (`article_cid`) REFERENCES `category` (`cid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of article
-- ----------------------------
INSERT INTO `article` VALUES (1, '文章1', NULL, '内容1', '05ae5bc3292c4701bbf541bb82709e73.png', NULL, 1);
INSERT INTO `article` VALUES (2, '文章2', NULL, '内容2', '05ae5bc3292c4701bbf541bb82709e73.png', NULL, 2);
INSERT INTO `article` VALUES (3, '文章3', NULL, '内容3', '05ae5bc3292c4701bbf541bb82709e73.png', NULL, 3);
INSERT INTO `article` VALUES (4, '文章4  ', NULL, '<p>内容433</p><p>55</p>', '05ae5bc3292c4701bbf541bb82709e73.png', '内容43355...', 4);
INSERT INTO `article` VALUES (5, '文章5  ', 1557920304913, '<p>内容5333</p><p><br/></p>', '2c71fe27368c4100a480e9045dfac258.jpg', '内容5333...', 10);
INSERT INTO `article` VALUES (6, '文章6', NULL, '内容6', '05ae5bc3292c4701bbf541bb82709e73.png', NULL, 5);

-- ----------------------------
-- Table structure for category
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category`  (
  `cid` int(255) NOT NULL AUTO_INCREMENT,
  `cname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `parentid` int(255) NULL DEFAULT NULL,
  PRIMARY KEY (`cid`) USING BTREE,
  INDEX `cid`(`cid`) USING BTREE,
  INDEX `cid_2`(`cid`, `parentid`) USING BTREE,
  INDEX `parentid`(`parentid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of category
-- ----------------------------
INSERT INTO `category` VALUES (1, 'JAVA', 0);
INSERT INTO `category` VALUES (2, 'Python', 0);
INSERT INTO `category` VALUES (3, '大前端', 0);
INSERT INTO `category` VALUES (4, 'Java Web', 1);
INSERT INTO `category` VALUES (5, 'Hibernate', 1);
INSERT INTO `category` VALUES (6, 'Struts', 1);
INSERT INTO `category` VALUES (7, 'Spring', 1);
INSERT INTO `category` VALUES (8, '机器语言', 2);
INSERT INTO `category` VALUES (9, '爬虫', 2);
INSERT INTO `category` VALUES (10, '画图', 2);
INSERT INTO `category` VALUES (11, '大数据', 2);
INSERT INTO `category` VALUES (12, 'Vue', 3);
INSERT INTO `category` VALUES (13, 'json', 3);

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '1', '1');
INSERT INTO `user` VALUES (2, 'admin', 'admin');

SET FOREIGN_KEY_CHECKS = 1;

建立domain

Article类

package com.le.domian;

import lombok.Getter;
import lombok.Setter;

@Getter@Setter
public class Article {
    private Integer article_id;
    private String article_title;
    private Long 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 +
                '}';
    }
}

关系映射Article.hbm.xml
<?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.le.domian.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.le.domian.Category" column="article_cid"/>

    </class>
</hibernate-mapping>

查询文章列表数据

发送请求

<frame src="${pageContext.request.contextPath}/article_list.action" name="mainFrame" >

配置接收请求

public class ArticleAction extends ActionSupport implements ModelDriven<Article> {
    private Article article = new Article();
    @Override
    public Article getModel() {
        return article;
    }
    //注入
    @Setter
    private ArticleService articleService;
    public String list(){
        System.out.println("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">/WEB-INF/mgr/mgr_main.jsp</result>
	<result name="edit">/WEB-INF/mgr/mgr_edit_article.jsp</result>
	<result name="listres" type="redirectAction">article_list.action</result>
	<allowed-methods>list,pageList,delete,getCategory,add,edit,update</allowed-methods>
</action>

<!--文章-->
<bean id="articleAction" class="com.le.web.ArticleAction" scope="prototype">
	<property name="articleService" ref="ArticleService"/>
</bean>
<bean id="ArticleService" class="com.le.service.impl.ArticleServiceImpl">
	<property name="articleDao" ref="ArticleDao"/>
</bean>
<bean id="ArticleDao" class="com.le.dao.impl.ArticleDaoImpl">
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

调用服务层

@Transactional
public class ArticleServiceImpl implements ArticleService {
    //注入
    @Setter
    private ArticleDao articleDao;
    @Override
    public List<Article> getAllArticle() {
        //调用dao
        return articleDao.getAllArticle();
    }
}    

调用dao层

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

解决no-session延迟加载问题

产生原因
	关联对象默认都是采用延迟加载
	事务都是在业务层开启和提交的
	所以调用完业务层后, 事务已经提交,session已经关闭了
	由于关联的对象延迟加载 当使用关联对象时, session已经不在了, 所以会报no-session异常
解决办法
	1.不使用延迟加载
		效率太低
	2.使用spring提供的解决方案OpenInViewFilter
		提供了一个过滤器
		在web视图层提供session的打开和关闭

web.xml

<!--配置延迟加载-->
<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>

展示所有列表

public class ArticleAction extends ActionSupport implements ModelDriven<Article> {
    private Article article = new Article();
    @Override
    public Article getModel() {
        return article;
    }
    //注入
    @Setter
    private ArticleService articleService;
    public String list(){
        //调用业务层
        List<Article> allArticle = articleService.getAllArticle();
        //把数据存取值栈当中,转发到jsp
        ActionContext.getContext().getValueStack().set("allArticle",allArticle);
        return "list";
    }
}    

<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="${ctx}/article_edit.action?article_id=<s:property value="#article.article_id"/>">
				<img class="img_icon" src="${ctx }/images/edit_icon.png" alt="">
			</a>
		</li>
		<li>
			<a href="${ctx }/article_delete.action?article_id=<s:property value="#article.article_id"/>">
				<img class="img_icon" src="${ctx }/images/delete_icon.png" alt="">
			</a>
		</li>
	</ul>
</s:iterator>


分页展示文章

构建pageBean

​ 相关属性
PageBean类

package com.le.domian;

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:<s:property value="currentPage"/>,
	totalPage: <s:property value="totalPage"/>,
	totalSize: <s:property value="totalCount"/>,
	callback: function(num) {
		//获取搜索关键字
		var keyWord = $("#input_search").val();
		$(window).attr('location','/article_pageList.action?currPage='+num+"&keyWord="+keyWord);
	}
})

<ul class="title_ul">
	<li>序号</li>
	<li>标题</li>
	<li>分类</li>
	<li>编辑</li>
	<li>删除</li>
</ul>

<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="${ctx}/article_edit.action?article_id=<s:property value="#article.article_id"/>">
				<img class="img_icon" src="${ctx }/images/edit_icon.png" alt="">
			</a>
		</li>
		<li>
			<a href="${ctx }/article_delete.action?article_id=<s:property value="#article.article_id"/>">
				<img class="img_icon" src="${ctx }/images/delete_icon.png" alt="">
			</a>
		</li>
	</ul>
</s:iterator>

web层接收请求
/*获取分页数据*/
@Setter
private Integer currPage = 1;
//搜索的关键字
@Setter
private String keyWord;
public String pageList(){
	//离线查询条件
	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
	//设置条件
	if(keyWord != null){
		//添加条件
		detachedCriteria.add(Restrictions.like("article_title","%"+keyWord+"%"));
	}
	//调用业务层
	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">/WEB-INF/mgr/mgr_main.jsp</result>
	<result name="edit">/WEB-INF/mgr/mgr_edit_article.jsp</result>
	<result name="listres" type="redirectAction">article_pageList.action</result>
	<interceptor-ref name="loginInterceptor">
		<param name="excludeMethods">getCategory</param>
	</interceptor-ref>
	<interceptor-ref name="defaultStack"></interceptor-ref>
	<allowed-methods>list,pageList,delete,getCategory,add,edit,update</allowed-methods>
</action>

服务层处理

@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);
	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;
}

搜索文章

点击搜索获取搜索内容发送给服务器

<div class="am-u-sm-12 am-u-md-3">
	<div class="am-input-group am-input-group-sm">
		<input type="text" class="am-form-field" id="input_search" value="<s:property value="#parameters.keyWord"/>">
		<span class="am-input-group-btn">
			<button class="am-btn am-btn-default" type="button" id="input_search_btn">搜索</button>
		</span>
	</div>
</div>

$("#input_search_btn").click(function () {
	//获取搜索关键字
	var keyWord = $("#input_search").val();
	//发送请求
	$(window).attr('location','/article_pageList.action?keyWord='+keyWord);
});

设置查询条件

/*获取分页数据*/
@Setter
private Integer currPage = 1;
//搜索的关键字
@Setter
private String keyWord;
public String pageList(){
	//离线查询条件
	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
	//设置条件
	if(keyWord != null){
		//添加条件
		detachedCriteria.add(Restrictions.like("article_title","%"+keyWord+"%"));
	}
	//调用业务层
	PageBean pageBean = articleService.getPageData(detachedCriteria,currPage,5);
	//数据存到值栈当中
	ActionContext.getContext().getValueStack().push(pageBean);
	return "list";
}

删除

获取当前点的文章id发送删除请求

<li>
	<a href="${ctx }/article_delete.action?article_id=<s:property value="#article.article_id"/>">
		<img class="img_icon" src="${ctx }/images/delete_icon.png" alt="">
	</a>
</li>

接收请求

/*删除*/
public String delete(){
	//调用业务层
	Article article2 = new Article();
	article2.setArticle_id(article.getArticle_id());
	articleService.delete(article2);
	return "listres";
}

处理删除业务

@Override
public void delete(Article article) {
	articleDao.delete(article);
}

数据库dao删除文章

@Override
public void delete(Article article) {
	this.getHibernateTemplate().delete(article);
}

返回到文章列表

<!--文章action-->
<action name="article_*" class="articleAction" method="{1}">
	<result name="list">/WEB-INF/mgr/mgr_main.jsp</result>
	<result name="edit">/WEB-INF/mgr/mgr_edit_article.jsp</result>
	<result name="listres" type="redirectAction">article_pageList.action</result>
	<allowed-methods>list,pageList,delete,getCategory,add,edit,update</allowed-methods>
</action>

添加文章

跳转到添加界面

分类列表框
<div class="item1">
	<span>所属分类:</span>
	<select id="category_select" name="category.parentid" style="width: 150px">&nbsp;&nbsp;
	</select>
	<select id="skill_select" name="category.cid" style="width: 150px">&nbsp;&nbsp;
	</select>
</div>

异步请求获取分类数据
//发送请求获取分类的数据
$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":0},function (data) {
	console.log(data);
	//遍历
	$(data).each(function (i,obj) {
		console.log(obj.cname);
		$("#category_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
	});
	//触发change
	$("#category_select").trigger("change");
},"json");

服务器接收请求处理
@Setter
private Integer parentid;
public  String getCategory() throws IOException {
	//根据parentid查询分类
	List<Category> list = articleService.getCategory(parentid);
	//把查询的结果转成json
	//以json(数据格式) 响应给页面
	JSONArray jsonArray = JSONArray.fromObject(list, new JsonConfig());
	//响应给页面
	ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
	ServletActionContext.getResponse().getWriter().println(jsonArray.toString());
	return null;
}

监听分类改变事件
//监听分类select改变
$("#category_select").on("change",function () {
	//获取当前选中的id
	var cid =  $("#category_select").val();

	//发送请求获取分类的数据
	$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":cid},function (data) {
		console.log(data);
		//遍历
		//清空之前标签
		$("#skill_select").empty();
		$(data).each(function (i,obj) {
			console.log(obj.cname);
			$("#skill_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
		});
	},"json");
});

选择图片

上传图片页面
<div class="item1 update_pic" >
	<span>摘要图片:</span>
	<img src="" id="imageview" class="item1_img" style="display: none;" >
	<label for="fileupload" id="label_file">上传文件</label>
	<input type="file" name="upload" id="fileupload"/>
</div>

/*原理是把本地图片路径:"D(盘符):/image/..."转为"http://..."格式路径来进行显示图片*/
$("#fileupload").change(function() {
	var $file = $(this);
	var objUrl = $file[0].files[0];
	//获得一个http格式的url路径:mozilla(firefox)||webkit or chrome
	var windowURL = window.URL || window.webkitURL;
	//createObjectURL创建一个指向该参数对象(图片)的URL
	var dataURL;
	dataURL = windowURL.createObjectURL(objUrl);
	$("#imageview").attr("src",dataURL);
	console.log($('#imageview').attr('style'));
	if($('#imageview').attr('style') === 'display: none;'){
		$('#imageview').attr('style','inline');
		$('#imageview').width("300px");
		$('#imageview').height("180px");
		$('.update_pic').attr('style', 'margin-bottom: 150px;');
	}
});

上传图片

​ 1.form表单enctype设置
​ multipart/form-data
​ 2.服务器提供属性接收

​ 3.上传文件处理

//添加文章
/**
 * 文件上传提供的三个属性:
 */
@Setter
private String uploadFileName; // 文件名称
@Setter
private File upload; // 上传文件
@Setter
private String uploadContentType; // 文件类型
public String add() throws IOException {

	if(upload != null){
		//上传文件
		//随机生成文件名称
		//1.获取文件扩展名  ssh.jpg
		int index = uploadFileName.lastIndexOf(".");
		String etx = uploadFileName.substring(index);
		//2.随机生成文件名  拼接扩展名
		String uuid = UUID.randomUUID().toString();
		String uuidFileName = uuid.replace("-", "") + etx;
		System.out.println(uuidFileName);

		//确定上传的路径
		String path = ServletActionContext.getServletContext().getRealPath("/upload");
		File file = new File(path);
		if(!file.exists()){
			file.mkdirs();
		}
		//拼接新文件路径
		File desFile = new File(path + "/" + uuidFileName);
		//文件上传
		FileUtils.copyFile(upload,desFile);
		//设置图片
		article.setArticle_pic(uuidFileName);
	}
	//设置当前时间
	article.setArticle_time(new Date().getTime());
	//调用业务层,保存到数据库当中
	articleService.save(article);
	return "listres";
}

集成富文本编辑器

umedit下载地址

添加到页面添加
1.引入js
	<script type="text/javascript" charset="utf-8" src="${ctx }/js/umedit/ueditor.config.js"></script>
	<script type="text/javascript" charset="utf-8" src="${ctx }/js/umedit/ueditor.all.min.js"> </script>
	<script type="text/javascript" charset="utf-8" src="${ctx }/js/umedit/lang/zh-cn/zh-cn.js"></script>
2.在页面当中提供div标签供显示内容
	<div id="editor" name="article_content" style="width:900px;height:400px;"></div>
3.在js当中初始化富文本编辑器
	//初始化富文本编程器
	var ue = UE.getEditor('editor');
	ue.ready(function () {
		ue.execCommand("inserthtml",$("#resContent").val());
	});

富文本编辑器文件上传

​ 1.添加uedit相关jar包

commons-codec-1.9.jar
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
json.jar
ueditor-1.1.2.jar

​ 2.配置过滤器

public class MyFilter extends StrutsPrepareAndExecuteFilter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        //获取当前的请求
        HttpServletRequest request = (HttpServletRequest)req;
        //获取请求地址来进行判断
        String requestURI = request.getRequestURI();
        if(requestURI.contains("js/umedit/jsp/controller.jsp")){
            //放行
            chain.doFilter(req,res);
        }else {
            super.doFilter(req,res,chain);
        }
    }
}

​ 3.json文件(js/umedit/jsp/config.json)配置获取图片路径

"imageUrlPrefix": "http://localhost:8080/", /* 图片访问路径前缀 */
"imagePathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */

发布文章

提交表单参数
<div id="editor" name="article_content" style="width:900px;height:400px;"></div>

$("#send").click(function () {
	//设置文本的描述
	//获取富文本正文
	var text = ue.getContentTxt();
	text = text.substring(0,150)+"...";
	//设置描述
	$("#article_desc").val(text);
	//提交表单
	$("#blog_form").submit();
});

服务器接收参数
//添加文章
/**
 * 文件上传提供的三个属性:
 */
@Setter
private String uploadFileName; // 文件名称
@Setter
private File upload; // 上传文件
@Setter
private String uploadContentType; // 文件类型
public String add() throws IOException {
	if(upload != null){
		//上传文件
		//随机生成文件名称
		//1.获取文件扩展名  ssh.jpg
		int index = uploadFileName.lastIndexOf(".");
		String etx = uploadFileName.substring(index);
		//2.随机生成文件名  拼接扩展名
		String uuid = UUID.randomUUID().toString();
		String uuidFileName = uuid.replace("-", "") + etx;
		//确定上传的路径
		String path = ServletActionContext.getServletContext().getRealPath("/upload");
		File file = new File(path);
		if(!file.exists()){
			file.mkdirs();
		}
		//拼接新文件路径
		File desFile = new File(path + "/" + uuidFileName);
		//文件上传
		FileUtils.copyFile(upload,desFile);
		//设置图片
		article.setArticle_pic(uuidFileName);
	}
	//设置当前时间
	article.setArticle_time(new Date().getTime());
	//调用业务层,保存到数据库当中
	articleService.save(article);
	return "listres";
}

@Override
public void save(Article article) {
	articleDao.save(article);
}

@Override
public void save(Article article) {
	this.getHibernateTemplate().save(article);
}

修改文章

跳转更新界面
请求发送
<li>
	<a href="#"><img class="img_icon" src="../../images/edit_icon.png" alt=""></a>
</li>

接收请求获取当前更新数据,写到值栈当中
public String edit(){
	//从数据库当中获取当前的文章
	Article resarticle = articleService.getOneArticle(article.getArticle_id());
	//把查询的数据存放到值栈
	ActionContext.getContext().getValueStack().push(resarticle);
	//跳转到编辑界面
	 return  "edit";
}

显示标题
<span>文章标题:</span>
<input type="text" class="am-form-field" name="article_title" style="width: 300px"
value="<s:property value="article_title"/> "
>

获取分类
<div class="item1">
	<span>所属分类:</span>
	<select id="category_select" name="category.parentid" style="width: 150px">&nbsp;&nbsp;
	</select>
	<select id="skill_select" name="category.cid" style="width: 150px">&nbsp;&nbsp;
	</select>
</div>

默认分类选中

//发送请求获取分类的数据
$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":0},function (data) {
	console.log(data);
	//遍历
	$(data).each(function (i,obj) {
		console.log(obj.cname);
		$("#category_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
	});
	//设置默认分类
	$("#category_select option[value=<s:property value="category.parentid"/>]").prop("selected",true);
},"json");

var parentid = <s:property value="category.parentid"/>
//发送请求获取分类的数据
$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":parentid},function (data) {
	//遍历
	//清空之前标签
	$("#skill_select").empty();
	$(data).each(function (i,obj) {
		console.log(obj.cname);
		$("#skill_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
	});
	//设置默认分类
	$("#skill_select option[value=<s:property value="category.cid"/>]").prop("selected",true);
},"json");


//监听分类select改变
$("#category_select").on("change",function () {
	//获取当前选中的id
	var cid =  $("#category_select").val();
	//发送请求获取分类的数据
	$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":cid},function (data) {
		//遍历
		//清空之前标签
		$("#skill_select").empty();
		$(data).each(function (i,obj) {
			console.log(obj.cname);
			$("#skill_select").append("<option value="+obj.cid+">"+obj.cname+"</option>");
		});
	},"json");
});

图片显示

<div class="item1 update_pic" >
	<span>摘要图片:</span>
	<img src="${ctx}/upload/<s:property value="article_pic"/>" id="imageview" class="item1_img">
	<label for="fileupload" id="label_file">上传文件</label>
	<input type="file" name="upload" id="fileupload"/>
</div>

富文本内容显示
<input type="hidden" id="resContent" value="<s:property value="article_content"/>">
<input type="hidden" name="article_id"  value="<s:property value="article_id"/>">
<input type="hidden" name="article_pic" value="<s:property value="article_pic"/>">

//初始化富文本编程器
var ue = UE.getEditor('editor');
ue.ready(function () {
	ue.execCommand("inserthtml",$("#resContent").val());
});

更新文章
发送提交请求
$("#send").click(function () {
	//设置文本的描述
	//获取富文本正文
	var text = ue.getContentTxt();
	text = text.substring(0,150)+"...";
	//设置描述
	$("#article_desc").val(text);
	//提交表单
	$("#blog_form").submit();
});

<div class="item1">
	<div>
		<span>文章标题:</span>
		<input type="text" class="am-form-field" name="article_title" style="width: 300px">&nbsp;&nbsp;
	</div>
</div>

<input type="text" name="article_desc" id="article_desc" style="display: none;">


<div class="item1">
	<span>所属分类:</span>
	<select id="category_select" name="category.parentid" style="width: 150px">&nbsp;&nbsp;

	</select>

	<select id="skill_select" name="category.cid" style="width: 150px">&nbsp;&nbsp;

	</select>

</div>

<div class="item1 update_pic" >
	<span>摘要图片:</span>
	<img src="" id="imageview" class="item1_img" style="display: none;" >
	<label for="fileupload" id="label_file">上传文件</label>
	<input type="file" name="upload" id="fileupload"/>
</div>

<div id="editor" name="article_content" style="width:900px;height:400px;"></div>
<button class="am-btn am-btn-default" type="button" id="send" style="margin-top: 10px;">
	发布
</button>

接收请求

​ 判断是否更新图片,如果更新图片删除原来的图片

//修改
public String update() throws IOException {
	System.out.println(article);
	//判断有没有新上传的图片
	if(upload != null){
		//确定上传的路径
		String path = ServletActionContext.getServletContext().getRealPath("/upload");
		//获取图片名称
		String picname = article.getArticle_pic();
		//删除原有的图片
		if(picname != null || "".equals(picname)){
			File file = new File(path + picname);
			file.delete();
		}
		//上传文件
		//随机生成文件名称
		//1.获取文件扩展名  ssh.jpg
		int index = uploadFileName.lastIndexOf(".");
		String etx = uploadFileName.substring(index);
		//2.随机生成文件名  拼接扩展名
		String uuid = UUID.randomUUID().toString();
		String uuidFileName = uuid.replace("-", "") + etx;
		File file = new File(path);
		if(!file.exists()){
			file.mkdirs();
		}
		//拼接新文件路径
		File desFile = new File(path + "/" + uuidFileName);
		//文件上传
		FileUtils.copyFile(upload,desFile);
		//设置图片
		article.setArticle_pic(uuidFileName);
	}

	//设置时间
	article.setArticle_time(System.currentTimeMillis());

	//调用业务更新文章
	articleService.update(article);
	return "listres";
}

权限处理

1.把jsp文件放到web/WEB-INF当中

2.创建LocationAction,修改链接跳转

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

3.设置拦截器

创建拦截器

public class LoginInterceptor extends MethodFilterInterceptor {
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        //判断用户是否登录
        User user = (User) ServletActionContext.getRequest().getSession().getAttribute("curUser");
        if(user == null){
            //没有登录
            ActionSupport action = (ActionSupport)actionInvocation.getAction();
            action.addActionError("你还没有登录,没有权限访问");
            //跳转login
            return "login";
        }else{
            //对请求的方法来放行
            return actionInvocation.invoke();
        }
    }
}

配置拦截器

<package name="struts" extends="struts-default">
	<interceptors>
		<interceptor name="loginInterceptor" class="com.le.web.LoginInterceptor"></interceptor>
	</interceptors>
	<global-results>
		<result name="login">/mgr_login.jsp</result>
	</global-results>

	<action name="location_*" class="locationAction" method="{1}">
		<result name="left">/WEB-INF/mgr/mgr_left.jsp</result>
		<result name="top">/WEB-INF/mgr/mgr_top.jsp</result>
		<result name="account">/WEB-INF/mgr/mgr_account.jsp</result>
		<result name="add">/WEB-INF/mgr/mgr_add_article.jsp</result>
		<allowed-methods>left,top,account,add</allowed-methods>
	</action>

	<!--loginAciton_login.action-->
	<action name="loginAciton_*" class="loginAction" method="{1}">
		<result name="success">/WEB-INF/mgr/mgr_index.jsp</result>
		<result name="login_out" type="redirect">/mgr_login.jsp</result>
			<interceptor-ref name="loginInterceptor">
				 <param name="excludeMethods">login</param>
			</interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		<allowed-methods>login,loginout</allowed-methods>
	</action>
</package>

前端处理

前端首面

导航分类加载数据

var parentid = getParams("parentid");

if (parentid != null) {
	//根据parentid加载子级
	$.post("${pageContext.request.contextPath}/article_getCategory.action", {"parentid": parentid}, function (data) {
		console.log(data);
		var html = template('mytpl2', {list: data});
		$("#tab_content").html(html);
	}, "json");
	//in(4,5,6,7)
	//加载数据
	getPageList(1,parentid,null);
} else {
	//加载分页列表
	getPageList(1,null,null);
}

加载全部数据分页展示

发送请求
//加载分类数据
function getPageList(curPage,parentid,cid) {
	$.post("${ctx}/web_getPageList.action", {currPage: curPage,parentid:parentid,cid:cid}, function (data) {
		/*console.log(JSON.parse(data).list);*/
		console.log(data);
		var html = template('mytpl', {list: data.list});
		$("#content").html(html);
		//分页
		$("#page").paging({
			pageNo: data.currentPage,//当前页
			totalPage: data.totalPage,//总页数
			totalSize: data.totalCount,//总记录
			callback: function (num) {
				getPageList(num,parentid,cid);
			}
		});
	});
}

接收请求处理
@Setter
private ArticleService articleService;
/*获取分页数据*/
@Setter
private Integer currPage = 1;
@Setter
private Integer parentid;
@Setter
private Integer cid;
//前端分页
public void getPageList() throws IOException {
	//离线查询条件
	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
	if(parentid != null){
		List<Category> categorys = articleService.getCategory(parentid);
		//构建一个数组
		Object[] cidArrays = new Object[categorys.size()];
		for(int i = 0; i< categorys.size(); i++){
			Category category = categorys.get(i);
			cidArrays[i] = category.getCid();
		}
		//设置条件
		detachedCriteria.add(Restrictions.in("category.cid",cidArrays));
	}
	if(cid != null){
		detachedCriteria.add(Restrictions.eq("category.cid",cid));
	}
	//调用业务层进行查询
	PageBean pageBean = articleService.getPageData(detachedCriteria,currPage,5);
	JsonConfig jsonConfig = new JsonConfig();
	//hibernate 延时加载
	jsonConfig.setExcludes(new String[]{"handler", "hibernateLazyInitializer"});
	JSONObject jsonObject = JSONObject.fromObject(pageBean,jsonConfig);
	// 将JSON打印到页面:
	ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");
	ServletActionContext.getResponse().getWriter().println(jsonObject.toString());
}

JSTemplate
概述

​ template.js是一款JavaScript模板引擎,用来渲染页面的。

引入JSTemplate.js

<script src="${ctx}/js/template.js"></script>

使用方法

​ 定义模板

<script id="mytpl1" type="text/html">
	{{if isAdmin}}
	<p>admin</p>
	{{else if score > 60}}
	<p>mvp</p>
	{{else}}
	<p>error!</p>
	{{/if}}
	{{title}}
	<hr>
	{{each list as value index}}
	<p>{{index}}--{{value}}</p>
	{{/each}}
</script>

​ 设置模板数据

<script id="mytpl1" type="text/html">
    var data = {
        title: '射手',
        isAdmin: false,
        score:61,
        list: ['鲁班', '孙尚香', '黄忠', '马可波罗', '公孙离', '后裔', '咖罗']
    };
</script>

​ 时间戳

//时间戳转换
template.helper('dateFormat', function (date, format){

	date = new Date(date);
	var map = {
		"M": date.getMonth() + 1, //月份 
		"d": date.getDate(), //日 
		"h": date.getHours(), //小时 
		"m": date.getMinutes(), //分 
		"s": date.getSeconds(), //秒 
		"q": Math.floor((date.getMonth() + 3) / 3), //季度 
		"S": date.getMilliseconds() //毫秒 
	};
	format = format.replace(/([yMdhmsqS])+/g, function (all, t) {
		var v = map[t];
		if (v !== undefined) {
			if (all.length > 1) {
				v = '0' + v;
				v = v.substr(v.length - 2);
			}
			return v;
		} else if (t === 'y') {
			return (date.getFullYear() + '').substr(4 - all.length);
		}
		return all;
	});
	return format;
});

展示数据
<%--定义模板--%>
<script id="mytpl" type="text/html">
    {{each list as value}}
    <li class="content_item">
        <div class="blog-list-left" style="float: left;">
            <div class="main-title">
                <a href="detail.jsp?id={{value.article_id}}">{{value.article_title}}</a>
            </div>
            <p class="sub-title">{{value.article_desc}}</p>
            <div class="meta">
                {{value.article_time | dateFormat:'yyyy-MM-dd '}}
            </div>
        </div>
        <img src="${ctx}/upload/{{value.article_pic}}" alt="" class="img-rounded">
    </li>
    {{/each}}
</script>

​ 分页处理
<script>
	//加载分类数据
    function getPageList(curPage,parentid,cid) {
        $.post("${ctx}/web_getPageList.action", {currPage: curPage,parentid:parentid,cid:cid}, function (data) {
            /*console.log(JSON.parse(data).list);*/
            console.log(data);
            var html = template('mytpl', {list: data.list});
            $("#content").html(html);
            //分页
            $("#page").paging({
                pageNo: data.currentPage,//当前页
                totalPage: data.totalPage,//总页数
                totalSize: data.totalCount,//总记录
                callback: function (num) {
                    getPageList(num,parentid,cid);
			}
		});
	});
</script>

​ 加载分类数据

分类点击

//获取分类的数据
//发送请求获取分类的数据
$.post("${pageContext.request.contextPath}/article_getCategory.action",{"parentid":0},function (data) {

	//遍历
	$(data).each(function (i,obj) {
	   $("#nav").append("<li class='active'><a href='index.jsp?parentid="+ obj.cid+"'>"+ obj.cname +"</a></li>");
	});

},"json");

​ 前端获取参数方法
//获取当前参数
function getParams(key) {
	var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
	var r = window.location.search.substr(1).match(reg);
	if (r != null) {
		return unescape(r[2]);
	}
	return null;
}
获取子分类
var parentid = getParams("parentid");
if (parentid != null) {
	//根据parentid加载子级
	$.post("${pageContext.request.contextPath}/article_getCategory.action", {"parentid": parentid}, function (data) {
		console.log(data);
		var html = template('mytpl2', {list: data});
		$("#tab_content").html(html);
	}, "json");

	//in(4,5,6,7)
	//加载数据
	getPageList(1,parentid,null);

} else {
	//加载分页列表
	getPageList(1,null,null);
}
传参获取数据
@Setter
private ArticleService articleService;
/*获取分页数据*/
@Setter
private Integer currPage = 1;
@Setter
private Integer parentid;
@Setter
private Integer cid;
//前端分页
public void getPageList() throws IOException {
	//离线查询条件
	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Article.class);
	if(parentid != null){
		List<Category> categorys = articleService.getCategory(parentid);
		//构建一个数组
		Object[] cidArrays = new Object[categorys.size()];
		for(int i = 0; i< categorys.size(); i++){
			Category category = categorys.get(i);
			cidArrays[i] = category.getCid();
		}
		//设置条件
		System.out.println(Arrays.toString(cidArrays));
		detachedCriteria.add(Restrictions.in("category.cid",cidArrays));
	}

	if(cid != null){
		detachedCriteria.add(Restrictions.eq("category.cid",cid));
	}

	//调用业务层进行查询
	PageBean pageBean = articleService.getPageData(detachedCriteria,currPage,5);
	JsonConfig jsonConfig = new JsonConfig();
	//hibernate 延时加载
	jsonConfig.setExcludes(new String[]{"handler", "hibernateLazyInitializer"});
	JSONObject jsonObject = JSONObject.fromObject(pageBean,jsonConfig);
	// 将JSON打印到页面:
	ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");
	ServletActionContext.getResponse().getWriter().println(jsonObject.toString());

}

​ 加载子分类列表

//如果标签是动态加载的,就不能使用这种方式注册事件
/*$(".categroy_btn").click(function () {
	alert("111");
});*/

$("body").on("click",".categroy_btn",function () {
	//获取当前点击的cid
	var cid = $(this).data("cid");
	alert(cid);
	getPageList(1,null,cid);
});

//加载分类数据
function getPageList(curPage,parentid,cid) {
	$.post("${ctx}/web_getPageList.action", {currPage: curPage,parentid:parentid,cid:cid}, function (data) {
		console.log(data);
		var html = template('mytpl', {list: data.list});
		$("#content").html(html);
		//分页
		$("#page").paging({
			pageNo: data.currentPage,//当前页
			totalPage: data.totalPage,//总页数
			totalSize: data.totalCount,//总记录
			callback: function (num) {
				getPageList(num,parentid,cid);
			}
		});
	});
}

​ 前端详情页

点击列表传递id

<%--定义模板--%>
<script id="mytpl" type="text/html">
    {{each list as value}}
    <li class="content_item">
        <div class="blog-list-left" style="float: left;">
            <div class="main-title">
                <a href="detail.jsp?id={{value.article_id}}">{{value.article_title}}</a>
            </div>
            <p class="sub-title">{{value.article_desc}}</p>
            <div class="meta">
                {{value.article_time | dateFormat:'yyyy-MM-dd '}}
            </div>
        </div>
        <img src="${ctx}/upload/{{value.article_pic}}" alt="" class="img-rounded">
    </li>
    {{/each}}
</script>

​ 获取参数加载相应数据

<script>
    //获取当前参数
    function getParams(key) {
        var reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) {
            return unescape(r[2]);
        }
        return null;
    }
    //获取参数
    var id = getParams("id");

    //请求数据
    $.post("${pageContext.request.contextPath}/web_getDetail.action",{id:id},function (data) {
            console.log(data);
            $("#title").html(data.article_title);
            $("#content").html(data.article_content);
            $("#data-time").html(new Date(data.article_time).toLocaleDateString());
    });
</script>

​ 服务器处理

//根据id获取指定的文章
@Setter
private Integer id;
public void getDetail() throws IOException {
	Article oneArticle = articleService.getOneArticle(id);
	JsonConfig jsonConfig = new JsonConfig();
	//hibernate 延时加载
	jsonConfig.setExcludes(new String[]{"handler", "hibernateLazyInitializer"});
	JSONObject jsonObject = JSONObject.fromObject(oneArticle,jsonConfig);
	// 将JSON打印到页面:
	ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");
	ServletActionContext.getResponse().getWriter().println(jsonObject.toString());
}

​ 详细页显示

<article class="mainarea" style="display:block;">
	<div class="blog-tab">
		<div class="tab-content" >
			<div role="tabpanel" style="margin-left: 100px;" class="tab-pane fade in active" id="home">
				<div id="lk_blog_list" style="padding-left: 20px; width: 1000px" class="container">
					<div class="row">
						<ul class="blog-list">
							<li>
								<div class="blog-list-left">
									<div class="main-title" id="title"></div>
									<div style="color: #c2c2c2" id="data-time">2019-1-1</div>
									<hr>
									<div id="content"></div>
								</div>
							</li>
						</ul>
					</div>
				</div>
			</div>
		</div>
	</div>
</article>
posted @ 2019-05-17 20:07  海韵༒听心  阅读(480)  评论(2编辑  收藏  举报