怎样取消网站备案,高端网站设计服务商,网页游戏源码下载,范湖网站建设哪家便宜头部登录状态
shiro标签的引用
由于shiro标签不是html的原生标签#xff0c;所有我们需要先引入一个额外的依赖#xff0c;shiro的标签库(thymeleaf的拓展标签)。 dependencygroupIdcom.github.theborakompanioni/groupIdartifactIdthymel…头部登录状态
shiro标签的引用
由于shiro标签不是html的原生标签所有我们需要先引入一个额外的依赖shiro的标签库(thymeleaf的拓展标签)。 dependencygroupIdcom.github.theborakompanioni/groupIdartifactIdthymeleaf-extras-shiro/artifactIdversion2.0.0/version/dependency依赖添加好之后然后我们需要在com.fly.config.ShiroConfig 中初始化一下注入对应的Bean, 页面才能渲染出来 //用于thymeleaf模板使用shiro标签,shiro方言标签Beanpublic ShiroDialect shiroDialect() {return new ShiroDialect();}然后在需要使用shiro标签的html 文件的头部添加
html xmlns:thhttp://www.thymeleaf.orgxmlns:shirohttp://www.pollix.at/thymeleaf/shiro添加好之后就可以使用shiro:user/shiro:user 将要权限控制的内容包起来当然shiro 标签还有很多
用户信息存到session中
用户登录成功之后需要将用户的信息保存的session中。我们只需要在用户认证的方法中com.fly.shiro.OAuth2Realm 类的doGetAuthenticationInfo 方法中加上如下语句
// 将登陆信息放在sessionSecurityUtils.getSubject().getSession().setAttribute(profile,profile);经过如下如上设置我们就实现了登录头部状态的控制
完善个人信息
用户中心
用户中心主要就两个我发的贴和我收藏的贴 我发的帖子在这里插入代码片com.homework.controller.CenterController#center 查询条件只有用户id QueryWrapperPost wrapper new QueryWrapperPost().eq(user_id, getProfileId()).orderByDesc(created);IPageMapString, Object pageData postService.pageMaps(page, wrapper);request.setAttribute(pageData, pageData);
我的收藏 IPageMapString, Object pageData userCollectionService.pageMaps(page, new QueryWrapperUserCollection().eq(user_id, getProfileId()).orderByDesc(created));postService.join(pageData, post_id);request.setAttribute(pageData, pageData);基本设置
tab 切换回显的问题一个页面有多个tab如何让在选中tab 之后刷新不丢失原来的tab选中选项呢答案是在url 后面加上#这相当于标签的效果。 当前tab页标签定义 在static/mods/user.js 有如下语句 //显示当前tabif(location.hash){element.tabChange(user, location.hash.replace(/^#/, ));}element.on(tab(user), function(){var othis $(this), layid othis.attr(lay-id);if(layid){location.hash layid;}});我们在templates/common/static.html 放入了如下代码并修改下信息
script th:inlinejavascript th:if${session.profile ! null}layui.cache.page ;layui.cache.user {username: [[${session.profile.username}]],uid: [[${session.profile.id}]],avatar: [[${session.profile.avatar}]],experience: 0,sex: [[${session.profile.gender}]]};layui.config({version: 3.0.0,base: /mods/ //这里实际使用时建议改成绝对路径}).extend({fly: index}).use(fly);
/script通过上面代码我们把初始化layui的部分js代码页面中很多class或id 的div 就拥有了特定的监听或其他。其中就报货截取url 获取#后面的标签用于tab 回显功能还有头像的上传功能封装等。 加上了上面代码之后你会发现经常会有个异常的弹框那是浏览器控制台发现去访问/message/nums 的链接在index.js 文件中找到 新消息通知按照接口要求我们修改地址为/user/message/nums 并在添加该接口 ResponseBodyPostMapping(/message/nums)public Object getMessNums() {MapObject, Object result new HashMap();result.put(status, 0);result.put(count, 3);return result;}头像 头像上传接口com.fly.controller.CenterController#upload, 头像上传核心代码 String orgName file.getOriginalFilename();log.info(上传文件名为 orgName);
// 获取后缀名String suffixName orgName.substring(orgName.lastIndexOf(.));log.info(上传的后缀名为 suffixName);
// 文件上传后的路径String filePath Constant.uploadDir;if (avatar.equalsIgnoreCase(type)) {fileName /avatar/avatar_ getProfileId() suffixName;} else if (post.equalsIgnoreCase(type)) {fileName post/post_ DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) suffixName;}File dest new File(filePath fileName);
// 检查目录是否存在if (!dest.getParentFile().exists()) {dest.getParentFile().mkdir();}//上传文件file.transferTo(dest);log.info(上传成功之后文件的路径{}, dest.getPath());目前上传的图片我们是到了一个指定目录然后nginx或者tomcat是可以读取这个目录的所以可以通过url来访问一般来说我们把图片上传到云存储服务上。这里先这样弄了。 头像上传之后更新shiro 中的头像信息 AccountProfile profile getProfile();profile.setAvatar(url);图片上传之后更新图像信息
密码 密码重置接口com.fly.controller.CenterController#resetPwd 接口代码比较简单 ResponseBodyPostMapping(/resetPwd)public R restPwd(String nowpass, String pass) {//查询用户User user userService.getById(getProfileId());if (user null || !nowpass.equals(user.getPassword())) {return R.failed(密码不正确);}user.setPassword(pass);boolean result userService.updateById(user);return R.ok(result);}前端页面在 /user/setting.html 中
发表编辑博客
发表和编辑博客是同一个页面前端页面展示 ajax 请求代码 $(function() {layui.use(form, function() {var form layui.form;//监听提交form.on(submit(post), function (data) {$.ajax({url: /user/post,type: POST,data: data.field,success: function (res) {if (res.code 0) {layer.msg(操作成功);setTimeout(function () {location.href/post/ res.data;}, 1000);} else {layer.msg(res.msg);}}});return false;});});});后台接口在com.fly.controller.PostController类中 ResponseBodyPostMapping(/user/post)public R postArticle(Valid Post post, BindingResult bindingResult) {if (bindingResult.hasErrors()) {return R.failed(bindingResult.getFieldError().getDefaultMessage());}
// 新增文章if (post.getId() null) {post.setUserId(getProfileId());post.setModified(new Date());post.setCreated(new Date());post.setCommentCount(0);post.setEditMode(Constant.EDIT_HTML_MODEL);post.setLevel(0);post.setRecommend(false);post.setViewCount(0);post.setVoteDown(0);post.setVoteUp(0);post.setStatus(Constant.NORMAL_STATUS);} else {Post tempPost postService.getById(post.getId());if (tempPost.getUserId().equals(getProfileId())) {return R.failed(不是自己的帖子);}}postService.saveOrUpdate(post);// TODO: 2018/12/13 给所有订阅人发送消息return R.ok(post.getId());}显示渲染博客
我们原先的显示博客内容是通过如下标签来显示的
div classdetail-body photos th:text${post.content}/div但这样显示出来的内容明显和我们预览的不一样还需要经过layui的渲染所以我们要加上一段js代码。在body后面加上templates/post/index.html:253
scriptlayui.use([fly,face],function () {var $ layui.$,flylayui.fly;// 如果你是采用模板自带的编辑器你需要开启以下语句来解析$(.detail-body).each(function () {var othis $(this), html othis.html();othis.html(fly.content(html));});博文回显
用户编辑完博客之后点击提交保存之后就可以 调用/user/post 进行博文回显博客的地址com.fly.controller.PostController#index 博文回显主要博文用户分类以及评论信息核心代码如下 MapString, Object post postService.getMap(new QueryWrapperPost().eq(id, id));userService.join(post, user_id);categoryService.join(post, category_id);Assert.notNull(post, 该文章已被删除);req.setAttribute(post, post);req.setAttribute(currentCategoryId, post.get(category_id));PageComment page new Page();page.setCurrent(current);page.setSize(size);IPageMapString, Object pageData commentService.pageMaps(page, new QueryWrapperComment().eq(post_id, id).orderByDesc(created));userService.join(pageData, user_id);commentService.join(pageData, parent_id);req.setAttribute(pageData, pageData);前端页面在 templates/post/index.html 部分代码如下 页面效果如下
用户主页
博客评论功能
用户评论表
CREATE TABLE comment (id bigint(32) NOT NULL AUTO_INCREMENT COMMENT 主键ID,content longtext NOT NULL COMMENT 评论的内容,parent_id bigint(32) DEFAULT NULL COMMENT 回复的评论ID,post_id bigint(32) NOT NULL COMMENT 评论的内容ID,user_id bigint(32) NOT NULL COMMENT 评论的用户ID,vote_up int(11) unsigned NOT NULL DEFAULT 0 COMMENT “顶”的数量,vote_down int(11) unsigned NOT NULL DEFAULT 0 COMMENT “踩”的数量,level tinyint(2) unsigned NOT NULL DEFAULT 0 COMMENT 置顶等级,status tinyint(2) DEFAULT NULL COMMENT 评论的状态,created datetime NOT NULL COMMENT 评论的时间,modified datetime DEFAULT NULL COMMENT 评论的更新时间,PRIMARY KEY (id)
) ENGINEInnoDB AUTO_INCREMENT3 DEFAULT CHARSETutf8mb4;后端接口代码在在这里插入代码片 ResponseBodyPostMapping(/user/post/comment)public R commentAdd(Valid Comment comment, BindingResult bindingResult) {Post post postService.getById(comment.getPostId());Assert.isTrue(post ! null, 该帖子已被删除);comment.setUserId(getProfileId());comment.setCreated(new Date());comment.setModified(new Date());comment.setStatus(Constant.NORMAL_STATUS);// TODO 记录动作// TODO 通知作者commentService.save(comment);return R.ok(null);}前端页面在 templates/post/index.html 提交评论代码如下 ajax 代码如下 layui.use([fly,face],function () {var $ layui.$,flylayui.fly;// 如果你是采用模板自带的编辑器你需要开启以下语句来解析$(.detail-body).each(function () {var othis $(this), html othis.html();othis.html(fly.content(html));});var form layui.form;//监听提交form.on(submit(comment), function (data) {$.ajax({url:/user/post/comment,data: data.field,type:POST,success: function (res) {if (res.code 0) {layer.msg(操作成功);setTimeout(function () {location.reload();}, 1000);} else {layer.msg(res.msg);}}});return false;});});配置异步请求登录过滤器
在我们shiroConfig中我们配置了非ajax的请求直接跳转到登录页面但是受限的ajax请求则不能处理。 如未登录状态下直接评论文档我们应该给出 请先登录 的提示。 在shiro中有很多过滤器。其中org.apache.shiro.web.filter.authc.UserFilter 在此我们继承UserFilter然后重写redirectToLogin方法。
public class AuthFilter extends UserFilter {Overrideprotected void redirectToLogin(ServletRequest servletRequest, ServletResponse response) throws IOException {HttpServletRequest request (HttpServletRequest) servletRequest;// 异步请求要先登录String header request.getHeader(X-Requested-With);if (header ! null XMLHttpRequest.equals(header)) {Subject subject SecurityUtils.getSubject();if (!subject.isAuthenticated()) {response.setContentType(application/json;charsetUTF-8);response.getWriter().print(JSONUtil.toJsonStr(R.failed(请先登录!)));} else {super.redirectToLogin(servletRequest, response);}}}
}然后在com.fly.config.ShiroConfig中注入AuthFilter 的Bean Beanpublic AuthFilter authFilter(){return new AuthFilter();}博客收藏功能
由于我们收藏按钮是通过js动态生成的所以我们先在html中定义好存放收藏按钮的divid 为LAY_jieAdmin 在static/mods/jie.js 中 var asyncRender function () {var div $(.fly-admin-box), jieAdmin $(#LAY_jieAdmin);//查询帖子是否收藏if (jieAdmin[0] layui.cache.user.uid ! -1) {$.post(/user/post/collection/find,{postId: div.data(id)}, function (res) {console.log(--------------)jieAdmin.append(span classlayui-btn layui-btn-xs jie-admin (res.data.collection ? layui-btn-danger : ) typecollect data-type (res.data.collection ? remove : add) (res.data.collection ? 取消收藏 : 收藏) /span);});}}();其中layui.cache.user.uid 是在templates/common/static.html 中定义的。从上述代码中我们可以看出js 代码根据后端的返回值动态的生成 收藏 or 取消收藏 后端接口如下 ResponseBodyPostMapping(/user/post/collection/find)public R collectionFind(String postId) {int count userCollectionService.count(new QueryWrapperUserCollection().eq(post_id, postId).eq(user_id, getProfileId()));return R.ok(MapUtil.of(collection, count 0));}
按钮点击效果的实现代码如下 ,collect: function(div){var othis $(this), type othis.data(type);fly.json(/user/post/collection/ type /, {postId: div.data(id)}, function(res){if(type add){othis.data(type, remove).html(取消收藏).addClass(layui-btn-danger);} else if(type remove){othis.data(type, add).html(收藏).removeClass(layui-btn-danger);}});}};后端代码比较简单参见com.fly.controller.PostController 中的相关方法。
效果图
参考代码
https://github.com/XWxiaowei/FlyBlog/tree/v5-collection-center