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" >
<br/>
<span>分类名称:</span>
<input type="text" class="am-form-field" id="cname" >
<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" >
<br/>
<span>分类名称:</span>
<input type="text" class="am-form-field" id="cname2" >
<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" >
<br/>
<span>分类名称:</span>
<input type="text" class="am-form-field" id="cname2" >
<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">
</select>
<select id="skill_select" name="category.cid" style="width: 150px">
</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";
}
集成富文本编辑器
添加到页面添加
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">
</select>
<select id="skill_select" name="category.cid" style="width: 150px">
</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">
</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">
</select>
<select id="skill_select" name="category.cid" style="width: 150px">
</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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix