1、原理说明:
查询天气的api:https://www.sojson.com/open/api/weather/json.shtml?city=
直接在city=后面加上中文城市,就会返回json数据。
eg: https://www.sojson.com/open/api/weather/json.shtml?city=饶平
{"date":"20180730","message":"Success !","status":200,"city":"广州","count":1,
"data":{"shidu":"96%","pm25":15.0,"pm10":31.0,"quality":"优","wendu":"26","ganmao":"各类人群可自由活动",
"yesterday":{"date":"29日星期日","sunrise":"05:55","high":"高温 35.0℃","low":"低温 27.0℃","sunset":"19:11","aqi":49.0,"fx":"无持续风向","fl":"<3级","type":"多云","notice":"阴晴之间,谨防紫外线侵扰"},
"forecast":[
{"date":"30日星期一","sunrise":"05:56","high":"高温 34.0℃","low":"低温 26.0℃","sunset":"19:10","aqi":46.0,"fx":"南风","fl":"3-4级","type":"雷阵雨","notice":"带好雨具,别在树下躲雨"},
{"date":"31日星期二","sunrise":"05:56","high":"高温 35.0℃","low":"低温 27.0℃","sunset":"19:10","aqi":54.0,"fx":"南风","fl":"3-4级","type":"雷阵雨","notice":"带好雨具,别在树下躲雨"},
{"date":"01日星期三","sunrise":"05:57","high":"高温 35.0℃","low":"低温 28.0℃","sunset":"19:09","aqi":59.0,"fx":"西南风","fl":"3-4级","type":"多云","notice":"阴晴之间,谨防紫外线侵扰"},
{"date":"02日星期四","sunrise":"05:57","high":"高温 35.0℃","low":"低温 27.0℃","sunset":"19:09","aqi":65.0,"fx":"无持续风向","fl":"<3级","type":"雷阵雨","notice":"带好雨具,别在树下躲雨"},
{"date":"03日星期五","sunrise":"05:57","high":"高温 35.0℃","low":"低温 27.0℃","sunset":"19:08","aqi":61.0,"fx":"东南风","fl":"3-4级","type":"多云","notice":"阴晴之间,谨防紫外线侵扰"}]}}
2、说明
概要:该系统是供给查询天气的,todayWeather类是描述今天的天气的,Weather类是描述从昨天开始的天气到未来几天的天气,一般而言,利用city+date字段作为todayweather的id,利用city+date作为搜索Weather的值。查询天气时,当数据库不存在该数据的时候,直接访问 查询天气的api,然后会将该数据存储到数据库中去,但当不是第一次查询已经查过的内容的时候,是从数据库中读取出来,而不是去访问天气查询api,减少对天气查询api的访问次数。
数据库说明:采用NoSQL的mongodb,想要运行该程序,需要先搭建好数据库环境,其中账号密码见application.properties文件。此外,本是不需要手动建立数据库的,但是,由于第一次查询的时候,需要访问数据库,所以需要手动建立数据库,最好是存在一条信息。
3、代码
项目的目录:
3.1 pom.xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
3.2 application.properties
# 定位模板的目录
spring.mvc.view.prefix=classpath:/templates/
server.servlet.context-path=
server.port=8080
server.tomcat.uri-encoding=UTF-8
#mongodb 账号为:name 密码为:pass 数据库为test
spring.data.mongodb.uri=mongodb://name:pass@localhost:27017/test
3.3 TodayWeather 类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TodayWeather {
@Id
private String cityDate;
private String city;
private String date;
private String week;
private String shidu;
private String pm25;
private String pm10;
private String quality;
private String wendu;
private String ganmao;
}
3.4 Weather类
package com.zhang.entity;
/*
最近的天气
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Weather {
//一般会有5个相同的,所以,不能作为@Id,只能作为寻找的关键字
private String cityDate;
private String city;
private String date;
private String sunrise;
private String high;
private String low;
private String sunset;
private String aqi;
private String fx;
private String fl;
private String type;
private String notice;
}
3.5 TodayWeatherRepository
package com.zhang.repository;
public interface TodayWeatherRepository extends MongoRepository<TodayWeather,String> {
TodayWeather findByCityDate(String cityDate);
void deleteByCityDate(String cityDate);
}
3.6 WeatherRepository
package com.zhang.repository;
public interface WeatherRepository extends MongoRepository<Weather,String> {
List<Weather> findAllByCityDate(String cityDate);
void deleteAllByCityDate(String cityDate);
}
3.7 TodayWeatherService
package com.zhang.service;
@Service
public class TodayWeatherService {
@Autowired
private TodayWeatherRepository todayWeatherRepository;
@Autowired
private MongoTemplate mongoTemplate;
//获取
public TodayWeather getTodayWeather(String cityAndDate)
{
TodayWeather weather = new TodayWeather();
try {
//连表都没建立.....可以找吗??
/*if (todayWeatherRepository == null) {
return null;
}*/
weather = todayWeatherRepository.findByCityDate(cityAndDate);
if(weather == null)
{
System.out.println("weather = = null");
return null;
}
}
catch(MongoException e)
{
e.printStackTrace();
}
return weather;
}
//增加
public void addTodayWeather(TodayWeather todayWeather)
{
try{
System.out.println("addTodayWeather-----try");
if(todayWeather != null)
todayWeatherRepository.save(todayWeather);
else
System.out.println("something error");
}
catch(MongoException e)
{
System.out.println("addTodayWeather------Exception");
e.printStackTrace();
}
}
//删
public void deleteTodayWeather(String cityAndDate)
{
try{
todayWeatherRepository.deleteByCityDate(cityAndDate);
}
catch(MongoException e)
{
e.printStackTrace();
}
}
//改/更新
public void updateTodayWeather(TodayWeather todayweather)
{
try{
todayWeatherRepository.save(todayweather);
}
catch(MongoException e)
{
e.printStackTrace();
}
}
}
3.8 WeatherService
package com.zhang.service;
@Service
public class WeatherService {
@Autowired
private WeatherRepository weatherRepository;
@Autowired
private MongoTemplate mongoTemplate;
//获取 weather
public List<Weather> getWeatherList(String cityDate)
{
return weatherRepository.findAllByCityDate(cityDate);
}
//增加 weather
public void addWeatherList( List<Weather> weathers)
{
for ( Weather w : weathers )
weatherRepository.save(w);
}
//删除
public void deleteWeatherList(String cityAndDate)
{
weatherRepository.deleteAllByCityDate(cityAndDate);
}
}
3.9 ReturnWeather.java ==》是获取具体的天气数据的
package com.zhang.conmon;
@Component
public class ReturnWeather {
private JsonNode json = null;
private final String uri = "https://www.sojson.com/open/api/weather/json.shtml?city=";
private boolean getJsonData(String city)
{
System.out.println("getJsonData中的city:="+city);
//去 服务器 请求一个数据
RestTemplate rest = new RestTemplate();
//ResponseEntity<T>是Spring对HTTP请求响应的封装,
// 包括了几个重要的元素,如响应码、contentType、contentLength、响应消息体等。
//String.class,表示希望返回的body类型是String
ResponseEntity<String> response = rest.getForEntity(uri + city, String.class);
//查询为成功的状态码
if (response.getStatusCodeValue() == 200)
{
String strBody = response.getBody();
ObjectMapper mapper = new ObjectMapper();
try {
json = mapper.readTree(strBody);
return true;
} catch (IOException e) {
System.out.print("json初始化失败");
e.printStackTrace();
}
}
return false;
}
//用city来获取今天的天气
public TodayWeather getTodayWeather(String city)
{
if (json == null) {
boolean judge = getJsonData(city);
if (judge == false)
return null;
}
TodayWeather result = new TodayWeather();
try {
JsonNode data = json.get("data");
result.setShidu(data.get("shidu").toString());
result.setGanmao(data.get("ganmao").toString());
result.setPm10(data.get("pm10").toString());
result.setPm25(data.get("pm25").toString());
result.setQuality(data.get("quality").toString());
result.setWendu(data.get("wendu").toString());
String date="";
Calendar now= Calendar.getInstance();
date=date+now.get(Calendar.YEAR)+(now.get(Calendar.MONTH)+1)+now.get(Calendar.DATE);
System.out.println("日期为: "+date);
result.setDate(date);
System.out.println("城市为:"+city);
result.setCity(city);
String[] weeks = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
Calendar n=Calendar.getInstance();
int index= n.get(Calendar.DAY_OF_WEEK)-1;
result.setWeek(weeks[index]);
System.out.println("星期为:"+result.getWeek());
result.setCity(city);
System.out.println("city为:"+result.getCity());
result.setCityDate(city+date);
System.out.println("cityAndDate为:"+result.getCityDate());
} catch (Exception e) {
System.out.println("获取当天天气状况失败");
e.printStackTrace();
return null;
}
return result;
}
//用JsonNode作为参数
private Weather returnWth(JsonNode deal,String city) throws Exception
{
Weather result=new Weather();
String date="";
Calendar now= Calendar.getInstance();
date=date+now.get(Calendar.YEAR)+(now.get(Calendar.MONTH)+1)+now.get(Calendar.DATE);
// System.out.println("日期为: "+date);
result.setDate(date);
result.setCity(city);
result.setCityDate(city+date);
// System.out.println("weather: "+ result.getCityDate());
result.setAqi(deal.get("aqi").toString());
result.setDate(deal.get("date").toString());
result.setFl(deal.get("fl").toString());
result.setFx(deal.get("fx").toString());
result.setHigh(deal.get("high").toString());
result.setLow(deal.get("low").toString());
result.setNotice(deal.get("notice").toString());
result.setSunrise(deal.get("sunrise").toString());
result.setSunset(deal.get("sunset").toString());
result.setType(deal.get("type").toString());
return result;
}
//通过city获取昨天天气和天气展望
public Vector<Weather> getWeatherList(String city)
{
if(json==null)
{
boolean judge = getJsonData(city);
if(judge==false)
return null;
}
Vector<Weather> result = new Vector<Weather>();
try{
JsonNode yd=json.get("data").get("yesterday");
Weather yesterday = returnWth(yd,city);
Weather forecast;
result.add(yesterday);
JsonNode fc= json.get("data").get("forecast");
for(int i=0;i<5;i++)
{
//给returnWth的fc.get(i) 只是 forecast部分
forecast= returnWth(fc.get(i),city);
result.add(forecast);
}
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
return result;
}
}
3.10 WeatherController ==》 接受处理 该网页的api
@Controller
@RequestMapping("/weather")
public class WeatherController {
@Autowired
private ReturnWeather deal;
@Autowired
private TodayWeatherService todayWeatherService;
@Autowired
private WeatherService weatherService;
@RequestMapping(value="/{city}",method = RequestMethod.GET)
public String getWeatherInfo(@PathVariable("city")String city,Model model)
{
String date="";
Calendar now= Calendar.getInstance();
date=date+now.get(Calendar.YEAR)+(now.get(Calendar.MONTH)+1)+now.get(Calendar.DATE);
//若是没有建立表格,这个操作有问题!! 手动建立一个表格,让其存在
System.out.println("getWeatherInfo中的cityAndDate1: = "+city+date);
TodayWeather weather = todayWeatherService.getTodayWeather(city+date);
System.out.println("getWeatherInfo中的cityAndDate2: = "+city+date);
List<Weather> weatherList = weatherService.getWeatherList(city+date);
//也就是 在数据库中 没有 该数据
if( weather == null )
{
ReturnWeather deal = new ReturnWeather();
TodayWeather weatherToday = deal.getTodayWeather(city);
List <Weather> weatherSet= deal.getWeatherList(city);
weatherService.addWeatherList(weatherSet);
if(weatherToday != null)
{
model.addAttribute("TodayWth",weatherToday);
model.addAttribute("WthSet",weatherSet);
todayWeatherService.addTodayWeather(weatherToday);
}
else
{
System.out.print("设置error");
model.addAttribute("error","查询次数过快或城市名称不存在");
}
}
else//如果在数据库中存在,就直接读取数据库中的数据
{
System.out.println("从数据库中直接读取的数据: "+city+date+" 的天气");
model.addAttribute("TodayWth",weather);
model.addAttribute("WthSet",weatherList);
}
//返回weather页面
return "weather";
}
}
3.11 前端页面
<!DOCTYPE html>
<html xmlns="http://www.thymeleaf.org" xmlns:th="http://www.springframework.org/schema/mvc">
<head>
<title>weather forecast</title>
</head>
<body>
<h2>-----title------</h2>
<script th:inline="javascript">
var todayWeatherTest = [[${TodayWth}]];
var WthSetTest = [[${WthSet}]] ; //数组来的
var errorTest = [[${error}]];
if(todayWeatherTest!=null) {
document.write("<h2>今日天气</h2>");
document.write("时间:" + todayWeatherTest.date+todayWeatherTest.week);
document.write("<br>");
document.write("地点:" + todayWeatherTest.city);
document.write("<br>");
document.write("温度:" + todayWeatherTest.wendu);
document.write("<br>");
document.write("湿度:" + todayWeatherTest.shidu);
document.write("<br>");
document.write("温馨提示:" + todayWeatherTest.ganmao);
document.write("<br>");
document.write("空气质量:" + todayWeatherTest.quality);
document.write("<br>");
document.write("Pm2.5:" + todayWeatherTest.pm25);
document.write("<br>");
document.write("PM1.0:" + todayWeatherTest.pm10);
document.write("<br>");
if (WthSetTest != null) {
for (var i in WthSetTest) {
if (i === 0)
document.write("<h2>昨日天气</h2>");
else
document.write("<h2>天气展望</h2>");
document.write("时间: " + WthSetTest[i].date + "<br>");
document.write("日出:" + WthSetTest[i].sunrise + "<br>");
document.write("最高气温:" + WthSetTest[i].sunrise + "<br>");
document.write("最低气温:" + WthSetTest[i].sunset + "<br>");
document.write("aqi:" + WthSetTest[i].aqi + "<br>");
document.write("fx:" + WthSetTest[i].fx + "<br>");
document.write("fl:" + WthSetTest[i].fl + "<br>");
document.write("天气:" + WthSetTest[i].type + "<br>");
document.write("温馨提示:" + WthSetTest[i].notice + "<br>");
}
}
if (errorTest != null) {
document.write(errorTest.toString());
}
}
</script>
</body>
</html>
4、坑
4.1、有些城市返回的数据格式不太一样,部分数据不存在,例如:海南是缺少部分数据的,故是显示不了数据。
4.2、在todayWeather中设置city和date为主键,本来命名为cityAndDate,但是,在repository层中写接口的时候,会造成误会,要改成cityDate或者其他不造成冲突的。
4.3、mongodb的findAll功能,返回的数据将是List,不是Vector。
4.4、前后端的数据交互:
前端获得后端的数据采用 var test = [[${test}]]; 的形式。后端将数据加入到Model里面。
后端只是简单将url的参数作为 数据使用,没有其他复杂交互。
4.5 采用redis缓存的在接下来再继续完成。
5 、欢迎交流~~