目录
跨域通信
首先要解决的是跨域问题:react框架默认3000端口,然而springboot是8080端口,所以在后端要添加一个CorsConfig
后端代码
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
System.out.println("跨域配置");
registry.addMapping("/api/**")//我前端发起的请求是/api/的格式
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
};
}
}
同时前端也要添加
'Access-Control-Allow-Origin': '*'
请求头来告诉浏览器你要发起跨域请求了
前端代码
useEffect(() => {
// Fetch schedule data from backend API
fetch('http://localhost:8080/api/这里写你自己要访问的地址', {
headers: {
'Access-Control-Allow-Origin': '*'//就是这个请求头
}
})
.then(response => response.json())
.then(data => {
const formattedData = data.map(item => ({//这里是时间格式问题
...item,
startTime: new Date(item.startTime),
endTime: new Date(item.endTime)
}));
setScheduleData(formattedData);
console.log('成功发送请求:', data);
})
.catch(error => console.error(error));
}, []);
处理完后我发现还是不行,无法跨域访问,在一顿搜素后得知可能是由于浏览器的安全机制导致的。在跨域请求时,浏览器会先发送一个OPTIONS请求来确认服务器是否允许跨域请求,只有在服务器返回正确的响应头后,浏览器才会发送真正的请求。因此,需要在Spring Boot后端中添加对OPTIONS请求的处理,以便正确地响
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api")
public class MyController {
@RequestMapping(value = "/myEndpoint", method = RequestMethod.OPTIONS)
public ResponseEntity handle() {
HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
headers.add("Access-Control-Allow-Headers", "Content-Type");
headers.add("Access-Control-Max-Age", "3600");
return new ResponseEntity(headers, HttpStatus.OK);
}
}
应这些预检请求。
需要将 myEndpoint
替换为自己的请求路径。这个示例中的 /myEndpoint
只是一个示范,大家需要根据自己的实际情况来替换它。通过method不同来重载。
完成上述步骤后就成功获取到了数据了。
获取数据无法渲染
页面依然没有数据,但是通过控制台的输出我知道我获取到了数据,于是我又开始搜索是什么问题。
渲染时间差
找到了一个靠谱的答案说由于fetch请求需要一定的时间,因此在完成请求之前,组件已经被渲染,并且使用了默认的空数组作为数据源。可以将“ScheduleComponent”放在条件语句中,以确保只有在成功获取数据后才会显示组件。
与是我增加了代码
if (scheduleData.length === 0) {
return <div>Loading...</div>;
}
这样子请求完成之前显示一个loading状态,等待数据加载完成后再渲染ScheduleComponent。当scheduleData数组的长度为0时,将显示“Loading...”文本;否则,将显示ScheduleComponent。
但是依然无法正确渲染出来
Json格式问题
于是我觉得应该是数据的问题,如何在一小时的搜索和尝试下发现了问题,
@RestController返回json时Jackson库的默认配置是将属性名转换为小写!!!
然而Scheduler控件中要求的数据都是首字母大写,所以我找到了三种解决方法,其中第三种最简单方便。
- 使用@JsonProperty注解:使用@JsonProperty注解,可以将Java类的属性与JSON属性名称映射。例如:
public class MyObject { @JsonProperty("myProperty") private String myProperty; }
这将将Java属性“myProperty”映射到JSON属性“myProperty”。
- 使用@JsonNaming注解:@JsonNaming注解允许指定一个自定义命名策略,在Jackson序列化和反序列化期间使用该策略。例如:
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class MyObject {
private String myProperty;
}
这将使用驼峰式命名约定,将Java属性名称转换为JSON属性名称。
3.配置ObjectMapper:还可以通过配置ObjectMapper来自定义JSON序列化和反序列化期间使用的命名策略。例如:
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
return mapper;
}
}
这将创建一个自定义的ObjectMapper bean,它将使用大写驼峰式命名约定。然后将自动应用于所有使用Jackson库进行序列化和反序列化的Spring Bean。