1.目录结构:

2.需要注意的地方

2.1在WEB-INFO下新建

2.1.1 springMVC-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
">
<context:component-scan base-package="monster._52cc"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///kh75?useUnicode=true&amp;characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="xxx"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="monster._52cc.pojo"/>
<property name="typeAliases" value="monster._52cc.util.PageUtils"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven/>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="monster._52cc.mapper"/>
</bean>
<!--这是从Controller层使用@RestController注解引起从数据库到前台时间出现Long类型的时间(从1970-1-1至今的毫秒),解决SpringMVC 中@RestController 返回日期格式为时间戳-->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"/>
</bean>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>

2.1.2 web.xml

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>list.html</welcome-file>
</welcome-file-list>
</web-app>

2.2实体类,对应数据库中Data的字段上加注解 @DateTimeFormat(pattern = "yyyy-MM-dd")

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AirQualityIndex {
/**
* 记录编号
*/
private Integer id; /**
* 区域编号
*/
private Integer districtId; /**
* 检测时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date monitorTime; /**
* pm10值
*/
private Integer pm10; /**
* pm2.5值
*/
private Integer pm2_5; /**
* 监测站
*/
private String monitoringStation; /**
* 最后修改时间
*/
private String lastModifyTime;
}

2.3 暂时没有用到Mybatis的分页插件,所以自己写分页工具类

@ToString
public class PageUtils {
private Integer pageSize;
private Integer pageNo;
private Integer totalCount;
private Integer totalPages;
private Integer startRow;
/**
* 需要分页的对象
*/
private AirQualityIndex airQualityIndex; public PageUtils() {
} public PageUtils(Integer pageSize, Integer pageNo, Integer totalCount, AirQualityIndex airQualityIndex) {
this.pageSize = pageSize;
this.pageNo = pageNo;
this.totalCount = totalCount;
this.airQualityIndex = airQualityIndex; setStartRow(pageSize,pageNo);
setTotalPages(pageSize,totalCount);
} public Integer getPageSize() {
return pageSize;
} public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
} public Integer getPageNo() {
return pageNo;
} public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
} public Integer getTotalCount() {
return totalCount;
} public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
} public Integer getTotalPages() {
return totalPages;
} public void setTotalPages(Integer pageSize,Integer totalCount) {
this.totalPages = totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
} public Integer getStartRow() {
return startRow;
} public void setStartRow(Integer pageSize,Integer pageNo) {
this.startRow = (pageNo-1)*pageSize;
} public AirQualityIndex getAirQualityIndex() {
return airQualityIndex;
} public void setAirQualityIndex(AirQualityIndex airQualityIndex) {
this.airQualityIndex = airQualityIndex;
}
}

2.4 省去mapper的xml,使用注解写sql

注意查询的动态sql上要用<script></script>包起来

AirQualityIndexMapper.java

public interface AirQualityIndexMapper {

    @Delete("DELETE FROM air_quality_index where id = #{id}")
int deleteByPrimaryKey(Integer id); @Insert("INSERT INTO air_quality_index VALUES (NULL,#{districtId}, #{monitorTime}, #{pm10}, #{pm2_5}, #{monitoringStation}, #{lastModifyTime})")
int insert(AirQualityIndex airQualityIndex); @Update("UPDATE air_quality_index SET districtId = #{districtId},monitorTime = #{monitorTime},pm10 = #{pm10},pm2_5 = #{pm2_5},monitoringStation = #{monitoringStation},lastModifyTime = #{lastModifyTime} WHERE id = #{id}")
int updateByPrimaryKey(AirQualityIndex airQualityIndex); @Select("<script>" +
"SELECT a.*,d.name FROM air_quality_index a,district d WHERE a.districtId = d.id" +
"<if test='airQualityIndex != null and airQualityIndex.id != null'>" +
" AND a.id=#{airQualityIndex.id}" +
"</if>" +
"<if test='airQualityIndex != null and airQualityIndex.districtId != -1 and airQualityIndex.districtId != null'>" +
" AND a.districtId=#{airQualityIndex.districtId}" +
"</if>" +
"<if test='pageSize != null and startRow != null'>" +
" LIMIT #{startRow},#{pageSize}" +
"</if>" +
"</script>")
List<Map<String,Object>> selectByPrimaryKey(PageUtils pageUtils); @Select("<script>" +
" SELECT count(0) FROM air_quality_index" +
" <where>" +
" <if test='districtId != null and districtId != -1'>" +
" AND districtId=#{districtId}" +
" </if>" +
" </where>" +
"</script>")
int getTotalCount(AirQualityIndex airQualityIndex);
}

2.5 service中要注意的事情

2.5.1因为分页逻辑属于service要做的事,所以贴上对应serviceImp中的逻辑

AirQualityIndexServiceImpl.java中的selectByPrimaryKey(PageUtils pageUtils)

@Service
@Transactional
public class AirQualityIndexServiceImpl implements AirQualityIndexService {
@Autowired
private AirQualityIndexMapper airQualityIndexMapper; @Override
public int deleteByPrimaryKey(Integer id) {
return airQualityIndexMapper.deleteByPrimaryKey(id);
} @Override
public int insert(AirQualityIndex airQualityIndex) {
//todo获取当前系统时间
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2019-10-23 10:31:37
airQualityIndex.setLastModifyTime(sdf.format(d));
if (airQualityIndex.getDistrictId() == -1) {
return 0;
}
return airQualityIndexMapper.insert(airQualityIndex);
} @Override
public int updateByPrimaryKey(AirQualityIndex airQualityIndex) {
//todo获取当前系统时间
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2019-10-23 10:31:37
//设置时区
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
airQualityIndex.setLastModifyTime(sdf.format(d));
if (airQualityIndex.getDistrictId() == -1) {
return 0;
}
System.out.println(airQualityIndex);
return airQualityIndexMapper.updateByPrimaryKey(airQualityIndex);
} @Override
public List<Map<String, Object>> selectByPrimaryKey(PageUtils pageUtils) {
if(pageUtils.getPageNo()==null){
return airQualityIndexMapper.selectByPrimaryKey(pageUtils);
}
pageUtils.setTotalCount(airQualityIndexMapper.getTotalCount(pageUtils.getAirQualityIndex()));
pageUtils.setPageSize(5);
pageUtils.setTotalPages(pageUtils.getPageSize(), pageUtils.getTotalCount());
pageUtils.setStartRow(pageUtils.getPageSize(), pageUtils.getPageNo());
return airQualityIndexMapper.selectByPrimaryKey(pageUtils);
}
}

2.5.2其中,因为要实时保存修改时间,所以也在service中实现

//todo获取当前系统时间
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2019-10-23 10:31:37
//设置时区
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
airQualityIndex.setLastModifyTime(sdf.format(d));
if (airQualityIndex.getDistrictId() == -1) {
return 0;
}
System.out.println(airQualityIndex);

2.6最终的Controller文件

CenterControllerOfAir.java

@RestController
public class CenterControllerOfAir{
@Autowired
private AirQualityIndexService airQualityIndexService;
@Autowired
private DistrictService districtService; @RequestMapping("/deleteByPrimaryKey.do")
public int deleteByPrimaryKey(Integer id) {
return airQualityIndexService.deleteByPrimaryKey(id);
} @RequestMapping("/insert.do")
public int insert(AirQualityIndex airQualityIndex) {
if(airQualityIndex.getDistrictId()==-1 || airQualityIndex.getMonitoringStation()==null || airQualityIndex.getMonitorTime()==null || airQualityIndex.getPm2_5()==null || airQualityIndex.getPm10()==null){
return 0;
}
return airQualityIndexService.insert(airQualityIndex);
} @RequestMapping("/updateByPrimaryKey.do")
public int updateByPrimaryKey(AirQualityIndex airQualityIndex) {
if(airQualityIndex.getDistrictId()==-1 || airQualityIndex.getMonitoringStation()==null || "".equals(airQualityIndex.getMonitoringStation().trim()) || airQualityIndex.getMonitorTime()==null || airQualityIndex.getPm2_5()==null || airQualityIndex.getPm10()==null){
return 0;
}
return airQualityIndexService.updateByPrimaryKey(airQualityIndex);
} @RequestMapping("/selectByPrimaryKey.do")
public Map<String, Object> selectByPrimaryKey(PageUtils pageUtils) {
Map<String, Object> map = new HashMap<>(16);
List<Map<String, Object>> airQualityIndexList = airQualityIndexService.selectByPrimaryKey(pageUtils);
map.put("airQualityIndexList",airQualityIndexList);
map.put("pageUtils",pageUtils);
return map;
} @RequestMapping("/showAllDistrict.do")
public List<Map<String, Object>> showAllDistrict() {
return districtService.showAllDistrict();
} @RequestMapping("/info.do")
public Map<String, Object> info(PageUtils pageUtils) {
Map<String, Object> map = new HashMap<>(16);
map.put("airQualityIndex",airQualityIndexService.selectByPrimaryKey(pageUtils).get(0));
map.put("optionData",districtService.showAllDistrict());
return map;
}
}

2.7对应的几个页面要注意的:

list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<center>
<h1>空气质量监测信息库</h1>
<form id="selDistrictForm">
按区域查询
<select name="districtId" id="selDistrictSel" title="区域查询">
<option value="-1">不限</option>
</select>
<input type="button" name="sel" value="查找"/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="add.html">添加空气质量信息</a>
</form>
<br/>
<table>
<tr>
<th>序号</th>
<th>区域</th>
<th>监测时间</th>
<th>PM10</th>
<th>PM2.5</th>
<th>监测站</th>
</tr>
</table>
<p class="pageFoot"></p>
</center>
<script rel="script" type="text/javascript" src="js/jquery-1.11.2.min.js"></script>
<script rel="script" type="text/javascript" src="js/initOptionSel.js"></script>
<script rel="script" type="text/javascript" src="js/list.js"></script>
</body>
</html>

list.js

$(function () {
// 初始化分页数据
initPageData(1);
//条件查找
$("[type=button]").click(function () {
initPageData(1);
}); }); function initPageData(pageNo) {
var table = $("table");
var pageFoot = $("[class=pageFoot]");
var districtId = $("[name=districtId]").val();
$.ajax({
url: "selectByPrimaryKey.do",
type: "post",
dataType: "json",
data: {"pageNo": pageNo, "airQualityIndex.districtId": districtId},
async: true,
success: function (obj) {
var tableStr = "";
console.log(obj.airQualityIndexList.length===0);
if (obj.airQualityIndexList.length===0){
$("tr:gt(0)").remove();
tableStr=`
<tr style="text-align: center">
<td colspan="6"><strong>抱歉,暂无数据</strong></td>
</tr>
`;
}else{
//在循环的前面清空标题以下的所有行
//获取行>0的那行.移除方法
$("tr:gt(0)").remove();
$.each(obj.airQualityIndexList, function (i) {
tableStr += `
<tr>
<td>${obj.airQualityIndexList[i].id}</td>
<td> <a href="edit.html?id=${obj.airQualityIndexList[i].id}">${obj.airQualityIndexList[i].name}</a></td>
<td>${obj.airQualityIndexList[i].monitorTime}</td>
<td>${obj.airQualityIndexList[i].pm10}</td>
<td>${obj.airQualityIndexList[i].pm2_5}</td>
<td>${obj.airQualityIndexList[i].monitoringStation}</td>
</tr>
`;
});
}
table.attr("width", "600");
table.append(tableStr);
$("tr").first().attr("style", "background-color:#ADD8E6");
$("tr:gt(0):odd").attr("style", "background-color:#90EE90"); //分页
//在分页前,清空原来分页的内容
pageFoot.html("");
var pageStr = "";
if(obj.pageUtils.totalCount===0){//如果没有数据,就不显示分页条
return ;
}
if (obj.pageUtils.pageNo === 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages) {//如果是第一页,并且还有下一页
pageStr = `
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">首&nbsp;页</a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;"><< 上一页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo + 1 });">下一页>></a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.totalPages});">尾&nbsp;页</a>
`
}else if (obj.pageUtils.pageNo === 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages) {//如果是第一页,并且没有有下一页
pageStr = ``//nothing to do
}else if(obj.pageUtils.pageNo !== 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages){//如果不是第一页,并且还有下一页
pageStr = `
<a href="javascript:void(0);" onclick="initPageData(1)">首&nbsp;页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo - 1 });"><< 上一页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo + 1 });">下一页>></a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.totalPages});">尾&nbsp;页</a>
`
}else if(obj.pageUtils.pageNo !== 1 && obj.pageUtils.pageNo === obj.pageUtils.totalPages){//如果不是第一页,且是最后一页
pageStr = `
<a href="javascript:void(0);" onclick="initPageData(1)">首&nbsp;页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo - 1 })"><< 上一页</a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">下一页>></a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">尾&nbsp;页</a>
`
}
pageStr += `
第&nbsp;
${obj.pageUtils.pageNo}
页/共
${obj.pageUtils.totalPages}
页(${obj.pageUtils.totalCount}条)
`;
pageFoot.append(pageStr);
},
error: function () {
alert("initPageData error");
}
})
}

2.7.1其中,分页逻辑可以以后稍作修改直接使用

            //分页
//在分页前,清空原来分页的内容
pageFoot.html("");
var pageStr = "";
if(obj.pageUtils.totalCount===0){//如果没有数据,就不显示分页条
return ;
}
if (obj.pageUtils.pageNo === 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages) {//如果是第一页,并且还有下一页
pageStr = `
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">首&nbsp;页</a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;"><< 上一页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo + 1 });">下一页>></a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.totalPages});">尾&nbsp;页</a>
`
}else if (obj.pageUtils.pageNo === 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages) {//如果是第一页,并且没有有下一页
pageStr = ``//nothing to do
}else if(obj.pageUtils.pageNo !== 1 && obj.pageUtils.pageNo !== obj.pageUtils.totalPages){//如果不是第一页,并且还有下一页
pageStr = `
<a href="javascript:void(0);" onclick="initPageData(1)">首&nbsp;页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo - 1 });"><< 上一页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo + 1 });">下一页>></a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.totalPages});">尾&nbsp;页</a>
`
}else if(obj.pageUtils.pageNo !== 1 && obj.pageUtils.pageNo === obj.pageUtils.totalPages){//如果不是第一页,且是最后一页
pageStr = `
<a href="javascript:void(0);" onclick="initPageData(1)">首&nbsp;页</a>|
<a href="javascript:void(0);" onclick="initPageData(${obj.pageUtils.pageNo - 1 })"><< 上一页</a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">下一页>></a>|
<a href="javascript:void(0);" style="text-decoration: none;color: grey;cursor:no-drop;">尾&nbsp;页</a>
`
}
pageStr += `
第&nbsp;
${obj.pageUtils.pageNo}
页/共
${obj.pageUtils.totalPages}
页(${obj.pageUtils.totalCount}条)
`;
pageFoot.append(pageStr);

initOptionSel.js

初始化下拉列表

$(function () {
//初始化查询下啦列表
initSelOption();}
);
function initSelOption() {
$.ajax({
url: "showAllDistrict.do",
type: "post",
dataType: "json",
data: {},
async: true,
success: function (obj) {
var str = "";
$.each(obj, function (i) {
str += `
<option value="${obj[i].id}">${obj[i].name}</option>
`
});
//获取下拉列表
$("#selDistrictSel").append(str);
},
error: function () {
alert("initSelOption error");
}
})
}
本文章转至 故事我忘了:
转载地址:https://www.cnblogs.com/jsccc520/p/11976748.html

空气质量管理系统ssm(mybatis+spring+springMVC)框架+前后端分离的更多相关文章

  1. myBatis+Spring+SpringMVC框架面试题整理

    myBatis+Spring+SpringMVC框架面试题整理(一) 2018年09月06日 13:36:01 新新许愿树 阅读数 14034更多 分类专栏: SSM   版权声明:本文为博主原创文章 ...

  2. 喜大普奔,两个开源的 Spring Boot + Vue 前后端分离项目可以在线体验了

    折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...

  3. 两个开源的 Spring Boot + Vue 前后端分离项目

    折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...

  4. SpringMVC+Spring+mybatis+maven+搭建多模块框架前后端分离开发框架的完整demo,拿走不谢。——猿实战02

            猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是 ...

  5. 一个实际的案例介绍Spring Boot + Vue 前后端分离

    介绍 最近在工作中做个新项目,后端选用Spring Boot,前端选用Vue技术.众所周知现在开发都是前后端分离,本文就将介绍一种前后端分离方式. 常规的开发方式 采用Spring Boot 开发项目 ...

  6. Spring Boot + Vue 前后端分离开发,权限管理的一点思路

    在传统的前后端不分的开发中,权限管理主要通过过滤器或者拦截器来进行(权限管理框架本身也是通过过滤器来实现功能),如果用户不具备某一个角色或者某一个权限,则无法访问某一个页面. 但是在前后端分离中,页面 ...

  7. 基于spring security 实现前后端分离项目权限控制

    前后端分离的项目,前端有菜单(menu),后端有API(backendApi),一个menu对应的页面有N个API接口来支持,本文介绍如何基于spring security实现前后端的同步权限控制. ...

  8. Spring Boot + Vue 前后端分离开发,前端网络请求封装与配置

    前端网络访问,主流方案就是 Ajax,Vue 也不例外,在 Vue2.0 之前,网络访问较多的采用 vue-resources,Vue2.0 之后,官方不再建议使用 vue-resources ,这个 ...

  9. Keycloak快速上手指南,只需10分钟即可接入Spring Boot/Vue前后端分离应用实现SSO单点登录

    登录及身份认证是现代web应用最基本的功能之一,对于企业内部的系统,多个系统往往希望有一套SSO服务对企业用户的登录及身份认证进行统一的管理,提升用户同时使用多个系统的体验,Keycloak正是为此种 ...

  10. 基于 Spring Security 的前后端分离的权限控制系统

    话不多说,入正题.一个简单的权限控制系统需要考虑的问题如下: 权限如何加载 权限匹配规则 登录 1.  引入maven依赖 1 <?xml version="1.0" enc ...

随机推荐

  1. 发布SaaS加速器:我们不做SaaS,我们只做SaaS生态的推进者和守护者

    摘要: 此次阿里云推出的SaaS加速器,涵盖商业中心.能力中心.技术中心三大板块,是阿里巴巴商业.能力和技术的一次合力输出:技术能力在这里沉淀为一个个模块,ISV和开发者只要通过简单的操作,写很少的代 ...

  2. 利用伪类选择器与better-scroll的on事件所完成的上拉加载

    之前给大家分享过一篇上拉加载 利用了better-scroll的pullUpDown 和DOM元素的删除添加  感觉那样不太好 今天给大家分享一个不同的上拉加载思想 代码如下 class List { ...

  3. saltStack 状态模块(状态间的关系)

    unless onlyif:状态间的条件判断,主要用于cmd状态模块 常用方法:    onlyif:检查的命令,仅当'onlyif'  选项指向的命令返回true时才执行name 定义的命 unle ...

  4. Samba服务器 安装

    yum -y install samba cp /etc/samba/smb.conf /etc/samba/smb.conf.bak cat >> /etc/samba/smb.conf ...

  5. 从 SGD 到 Adam —— 深度学习优化算法概览(一) 重点

    https://zhuanlan.zhihu.com/p/32626442 骆梁宸 paper插画师:poster设计师:oral slides制作人 445 人赞同了该文章 楔子 前些日在写计算数学 ...

  6. hdu 4063 Aircraft (Geometry + SP)

    Problem - 4063 几何加简单最短路. 题意是给出若干圆的圆心以及半径,求出从给出的起点到终点的最短路径的长度,可以移动的区域是圆覆盖到的任意一个位置. 做法是这样的,对圆两两求交点,用这些 ...

  7. hdu 1535 Invitation Cards(spfa)

    Invitation Cards Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  8. poj 2451 Uyuw's Concert (半平面交)

    2451 -- Uyuw's Concert 继续半平面交,这还是简单的半平面交求面积,不过输入用cin超时了一次. 代码如下: #include <cstdio> #include &l ...

  9. SuperSocket命令加载器 (Command Loader)

    在某些情况下,你可能希望通过直接的方式来加载命令,而不是通过自动的反射. 如果是这样,你可以实现你自己的命令加载器 (Command Loader): public interface IComman ...

  10. zoj 2954 Hanoi Tower

    Hanoi Tower Time Limit: 2 Seconds Memory Limit: 65536 KB You all must know the puzzle named "Th ...