4.0.0
com.csq.study
csq-weather-report
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.2.RELEASE
org.springframework.boot
spring-boot-starter-web
org.apache.httpcomponents
httpclient
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-starter-quartz
2.1.5.RELEASE
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-maven-plugin
package com.csq.study.springboot.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestConfiguration {
@Autowired
private RestTemplateBuilder builder;
@Bean
public RestTemplate restTemplate() {
return builder.build();
}
}
package com.csq.study.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.csq.study.springboot.service.CityDataService;
import com.csq.study.springboot.service.WeatherReportService;
@RestController
@RequestMapping("/report")
public class WeatherController {
@Autowired
private WeatherReportService WeatherReportService;
@Autowired
private CityDataService cityDataService;
@GetMapping("/cityId/{cityId}")
public ModelAndView getReportByCityId(@PathVariable("cityId") String cityId,Model model)throws Exception {
model.addAttribute("title", "天气预报测试");
model.addAttribute("cityId", cityId);
model.addAttribute("cityList", cityDataService.listCity());
model.addAttribute("report", WeatherReportService.getDataByCityId(cityId));
return new ModelAndView("report","reportModel",model);
}
}
package com.csq.study.springboot.service;
import java.util.List;
import com.csq.study.springboot.vo.City;
接口:
public interface CityDataService {
/**
*
* @Title: listCity
* @Description: 获取城市列表
* @return
* @throws Exception
*
*/
List listCity() throws Exception;
}
实现类:
package com.csq.study.springboot.service.impl;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import com.csq.study.springboot.service.CityDataService;
import com.csq.study.springboot.util.XmlBuilder;
import com.csq.study.springboot.vo.City;
import com.csq.study.springboot.vo.CityList;
@Service
public class CityDataServiceImpl implements CityDataService{
@Override
public List listCity() throws Exception {
//读取xml文件
Resource resource=new ClassPathResource("cityList.xml");
BufferedReader br=new BufferedReader(new InputStreamReader(resource.getInputStream(),"utf-8"));
StringBuffer buffer=new StringBuffer();
String line="";
while((line=br.readLine())!=null){
buffer.append(line);
}
br.close();
//xml转为Java对象
CityList cityList= (CityList) XmlBuilder.xmlStrToObject(CityList.class, buffer.toString());
return cityList.getCityList();
}
}
接口:
package com.csq.study.springboot.service;
import com.csq.study.springboot.vo.WeatherResponse;
public interface WeatherDataService {
//根据城市ID查询天气数据
WeatherResponse getDataByCityId(String cityId);
//根据城市名称查询天气数据
WeatherResponse getDataByCityName(String cityName);
//根据城市ID同步天气数据
void syncDataByCityId(String cityId);
}
实现类:
package com.csq.study.springboot.service.impl;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.csq.study.springboot.service.WeatherDataService;
import com.csq.study.springboot.vo.Weather;
import com.csq.study.springboot.vo.WeatherResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class WeatherDataServiceImpl implements WeatherDataService {
private final static Logger logger=LoggerFactory.getLogger(WeatherDataServiceImpl.class);
private static final String WEATHER_API="http://wthrcdn.etouch.cn/weather_mini?";
private final Long TIME_OUT=1800L;
@Autowired
private RestTemplate restTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public WeatherResponse getDataByCityId(String cityId) {
String uri=WEATHER_API + "citykey=" + cityId;
return this.doGetWeather(uri);
}
public WeatherResponse getDataByCityName(String cityName) {
String uri=WEATHER_API + "city=" + cityName;
return this.doGetWeather(uri);
}
@Override
public void syncDataByCityId(String cityId) {
String uri=WEATHER_API + "citykey=" + cityId;
this.doGetWeather(uri);
}
private WeatherResponse doGetWeather(String uri) {
ValueOperations ops = this.stringRedisTemplate.opsForValue();
String key=uri;//将调用的URI作为key
String strBody=null;
ObjectMapper mapper=new ObjectMapper();
WeatherResponse weather=null;
//先查缓存,缓存没有在查服务
if(!this.stringRedisTemplate.hasKey(key)) {
logger.info("没有找到key");
ResponseEntity response = restTemplate.getForEntity(uri, String.class);
if(response.getStatusCodeValue()==200) {
strBody=response.getBody();
}
ops.set(key, strBody, TIME_OUT, TimeUnit.SECONDS);
}else {
logger.info("找到key"+key+",value="+ops.get(key));
strBody=ops.get(key);
}
//用json反序列化成我们想要的数据
try {
/*
* strBody:要解析的参数内容,从respString获取
* WeatherResponse.class:要转成的对象类型
*/
weather=mapper.readValue(strBody,WeatherResponse.class);
}catch(IOException e) {
logger.error("Error!",e);
}
return weather;
}
}
接口:
package com.csq.study.springboot.service;
import com.csq.study.springboot.vo.Weather;
public interface WeatherReportService {
//根据城市id查询天气信息
Weather getDataByCityId(String cityId);
}
实现类:
package com.csq.study.springboot.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.csq.study.springboot.service.WeatherDataService;
import com.csq.study.springboot.service.WeatherReportService;
import com.csq.study.springboot.vo.Weather;
import com.csq.study.springboot.vo.WeatherResponse;
@Service
public class WeatherReportServiceImpl implements WeatherReportService{
@Autowired
private WeatherDataService weatherDataService;
@Override
public Weather getDataByCityId(String cityId) {
WeatherResponse response = weatherDataService.getDataByCityId(cityId);
return response.getData();
}
}
package com.csq.study.springboot.job;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.csq.study.springboot.service.CityDataService;
import com.csq.study.springboot.service.WeatherDataService;
import com.csq.study.springboot.vo.City;
@Component
public class ScheduledTasks {
private static final Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat formate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Autowired
private CityDataService cityDataService;
@Autowired
private WeatherDataService watherDataService;
@Scheduled(fixedRate = 30000)
public void scheduledDemo(){
logger.info("天气数据同步任务 开始 every 5 seconds:{}", formate.format(new Date()) );
List cityList=null;
try {
cityList=cityDataService.listCity();
} catch (Exception e) {
logger.info("获取异常",e);
}
for (City city : cityList) {
String cityId = city.getCityId();
logger.info("天气任务同步中,cityId:"+cityId);
//根据城市id获取天气
watherDataService.syncDataByCityId(cityId);
}
logger.info("天气任务同步End");
}
}
package com.csq.study.springboot.util;
import java.io.Reader;
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class XmlBuilder {
//将xml转为指定的POJO
public static Object xmlStrToObject(Class> clazz,String xmlStr) throws Exception{
Object xmlObject=null;
Reader reader=null;
JAXBContext context=JAXBContext.newInstance(clazz);
//xml转为对象的接口
Unmarshaller unmarshaller=context.createUnmarshaller();
reader=new StringReader(xmlStr);
xmlObject=unmarshaller.unmarshal(reader);
if(reader!=null){
reader.close();
}
return xmlObject;
}
}
package com.csq.study.springboot.vo;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
city类
//声明为xml的根元素
@XmlRootElement(name = "d")
//声明xml的访问类型为FIELD(字段)
@XmlAccessorType(XmlAccessType.FIELD)
public class City{
//声明为xml的属性
@XmlAttribute(name = "d1")
private String cityId;
//声明为xml的属性
@XmlAttribute(name = "d2")
private String cityName;
//声明为xml的属性
@XmlAttribute(name = "d3")
private String cityCode;
//声明为xml的属性
@XmlAttribute(name = "d4")
private String province;
public String getCityId() {
return cityId;
}
public void setCityId(String cityId) {
this.cityId = cityId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
@Override
public String toString() {
return "City [cityId=" + cityId + ", cityName=" + cityName + ", cityCode=" + cityCode + ", province="
+ province + "]";
}
}
package com.csq.study.springboot.vo;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
CityList 类
@XmlRootElement(name = "c")
@XmlAccessorType(XmlAccessType.FIELD)
public class CityList {
@XmlElement(name = "d")
private List cityList;
public List getCityList() {
return cityList;
}
public void setCityList(List cityList) {
this.cityList = cityList;
}
}
package com.csq.study.springboot.vo;
import java.io.Serializable;
Forecast 类
public class Forecast implements Serializable{
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = 1L;
private String date;//琪日期
private String high;//最高温度
private String fengxiang;//风向
private String low;//最低温度
private String fengli;//风力
private String type;//天气类型
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFengxiang() {
return fengxiang;
}
public void setFengxiang(String fengxiang) {
this.fengxiang = fengxiang;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFengli() {
return fengli;
}
public void setFengli(String fengli) {
this.fengli = fengli;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package com.csq.study.springboot.vo;
import java.io.Serializable;
import java.util.List;
Weather 类
public class Weather implements Serializable {
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = 1L;
private String city;
private String aqi;//
private String wendu;
private String ganmao;
private Yesterday yesterday;
private List forecast;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAqi() {
return aqi;
}
public void setAqi(String aqi) {
this.aqi = aqi;
}
public String getWendu() {
return wendu;
}
public void setWendu(String wendu) {
this.wendu = wendu;
}
public String getGanmao() {
return ganmao;
}
public void setGanmao(String ganmao) {
this.ganmao = ganmao;
}
public Yesterday getYesterday() {
return yesterday;
}
public void setYesterday(Yesterday yesterday) {
this.yesterday = yesterday;
}
public List getForecast() {
return forecast;
}
public void setForecast(List forecast) {
this.forecast = forecast;
}
}
package com.csq.study.springboot.vo;
import java.io.Serializable;
WeatherResponse 类
public class WeatherResponse implements Serializable{
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = 1L;
private Weather data; //消息数据
private String status; //消息状态
private String desc;//消息描述
public Weather getData() {
return data;
}
public void setData(Weather data) {
this.data = data;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.csq.study.springboot.vo;
import java.io.Serializable;
Yesterday 类
public class Yesterday implements Serializable{
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = 1L;
private String date;
private String high;
private String fx;
private String low;
private String fl;
private String type;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFx() {
return fx;
}
public void setFx(String fx) {
this.fx = fx;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getFl() {
return fl;
}
public void setFl(String fl) {
this.fl = fl;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package com.csq.study.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Aplication {
public static void main(String[] args) {
SpringApplication.run(Aplication.class, args);
}
}
/**
* report页面下拉框事件
*/
$(function(){
$("#selectCityId").change(function () {
var cityId=$("#selectCityId").val();
var url='/report/cityId/'+cityId;
window.location.href=url;
})
});
天气预报
天气
城市名称
空气质量指数:
当前温度:
温馨提示:
日期
天气类型
最高温度
最低温度
风向
#热部署静态文件
spring.thymeleaf.cache=false
运行之后,访问:http://localhost:8080/report/cityId/101010900 出现下面 截图就ok
下拉选选择不同的地方出现的就是不同地方的信息 ,若不出现,兹证明有地方没有处理好,需要去检查。