您的位置:首页 > 编程语言 > Java开发

QiYu Admin-架构搭建(SpringBoot实战)

2017-03-04 15:40 357 查看

简述

自从上周写了第一篇博客,我就开始不停的忙活起来我的项目了,真佩服现在的我还有那么大的精神,半夜4点突然醒了,然后就睡不着了,想着想着就打开了我的电脑,开始编写我那没有回报的后台管理系统的项目,我现在称之为QiYu Admin。只因为我的女儿叫做七语。

这个星期只要是下班时间我就疯狂的想我的博客,但是总得出点东西才能写啊,一周过去了,基本上时间都在框架和前端页面的封装上了,到现在还算出了一点点东西了,那就先出一篇吧,动漫在慢也会每周更新一集啊,先看下集成哪些东西吧:

shiro集成(认证)

Thymeleaf3.0集成和Shiro标签

异常页面自定义

一些前端框架的封装(layer、sweetalert、bootstrap-table等)

用户分页列表

用户修改页面

成果

一、首页



二、用户管理



表格用的BootStrap-table,分页自动影藏和展现,当超过设定每页的条数时自动回出来分页。

三、选中一个用户点击修改(Layer弹出和用户信息页面)



四、微妙微笑的弹出提示框

不能多选



不能选择一个



更多弹出框将在后续出来。

五、异常页面



具体实现

接下来就是对上述的成果进行详细的说明喽。

Shiro的配置和Thymeleaf标签

package com.qiyu.admin.auth.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* Shiro 配置 Apache Shiro 核心通过 Filter 来实现,就好像SpringMvc 通过DispachServlet 来主控制一样。
* 既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。
*/
@Configuration
public class ShiroConf {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/assets/**", "anon");
// 配置记住我或认证通过可以访问的地址
// filterChainDefinitionMap.put("/i
4000
ndex", "user");
// filterChainDefinitionMap.put("/", "user");
// <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(customRealm());
// 注入记住我管理器;
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
/**
* 身份认证realm; (这个需要自己写,账号密码校验;权限等)
* @return
*/
@Bean
public AuthCustomRealm customRealm() {
AuthCustomRealm customRealm = new AuthCustomRealm();
customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return customRealm;
}
/**
* 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* 所以我们需要修改下doGetAuthenticationInfo中的代码; )
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(3);// 散列的次数,比如散列两次,相当于md5(md5(""));
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
return hashedCredentialsMatcher;
}
/**
* 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* cookie对象;
* @return
*/
@Bean
public SimpleCookie rememberMeCookie() {
// 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// <!-- 记住我cookie生效时间30天 ,单位秒;-->
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
/**
* cookie管理对象;
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
return cookieRememberMeManager;
}
/**
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}


备注:至于源码很多都不是我自己原创出来的,都是通过网上的一些网友和朋友借鉴而来。其中比较有名是我的一个朋友林祥纤开设了专栏,《从零开始学spring boot》。

异常页面配置

其实也就是实现了ErrorController类(这些都可以在《从零开始学spring boot》里面找到),这里就不做赘述。

Layer封装

其实没啥技术含量就是把layer.open给封装了一下,方便以后类似的功能调用。

var layerOpen=function(title,width,height,content){
return layer.open({
type:2,
skin:"qiyu-custom-layer",
title: title,
area: [width,height],
fix: false, //不固定
shadeClose: true,
shade: 0.8,
scrollbar: false,
content: content
});
}


sweetalert封装(同上)

var bootstrapSweetAlert=function (sa_title,sa_message,sa_type) {
swal({
title: sa_title,
text: sa_message,
type: sa_type
});
}


Bootstrap-table封装(同上)

var initBootStrapTable=function(table,ajaxUrl,columns) {
table.bootstrapTable({
method: 'get',
url: ajaxUrl,
cache: false,
dataType: "json",
striped: false,  //使表格带有条纹
sortable: true,
pagination: true,   //在表格底部显示分页工具栏
pageSize: 8,
pageNumber: 1,
pageList: [5, 8, 10],
idField: "id",  //标识哪个字段为id主键
showToggle: false,   //名片格式
cardView: false,//设置为True时显示名片(card)布局
singleSelect: false,//复选框只能选择一条记录
search: false,//是否显示右上角的搜索框
clickToSelect: true,//点击行即可选中单选/复选框
sidePagination: "server",//表格分页的位置
queryParamsType: "", //参数格式,发送标准的RESTFul类型的参数请求
strictSearch: true,
showColumns: false,     //是否显示所有的列
showRefresh: false,     //是否显示刷新按钮
minimumCountColumns: 2,    //最少允许的列数
responseHandler: function (res) {
return {
"rows": res.dataList,
"total": res.total
};
},
silent: true,  //刷新事件必须设置
formatNoMatches: function () {  //没有匹配的结果
return '无符合条件的记录';
},
rowStyle: function (row, index) {
return {classes: "cursorHand"}
},
columns: columns
});
}


结语

其实都是站在巨人的肩膀上来做的,所以我把自己定位为我不是一个程序员、我不是一个架构师、我不是一个设计师。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐