空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结

时间:2023-03-10 07:03:58
空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结
作者:故事我忘了
个人微信公众号:程序猿的月光宝盒
空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结

1.目录结构:

空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结

2.需要注意的地方

2.1在WEB-INFO下新建

空气质量管理系统+SSM(Spring+SpringMVC+Mybatis)+前后端分离总结

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

以上,结束

点我进入对应的项目源码下载