SPAを作ろうとAngularに安易に手を出し、ハマったのでメモ
1.subscribeは必ず書く
まず接続テストだけのつもりでsubscribeメソッドを書かずにいたら全然つながらなかった
下記のgetItemとgetItem2のメソッドの違いはHttpResponse型で受け取るかどうかだけです
sample.service.ts
export interface Item{
title:string;
}
export class MaterialService {
//Angularでリバースプロキシ設定する場合
//private host: string = '/api';
//Angularでリバースプロキシ設定しない場合
private host: string = 'http://localhost:8080/api/v1';
constructor(private http: HttpClient) {}
getItem(){
const rtn:Observable<HttpResponse<Item>> = this.http.get<Item>(this.host+'/sample',{observe:'response'}).pipe(
timeout(5000),
catchError(this.handleError)
);
//この時点ではまだHTTP通信はされてない
//下記のsubscribeメソッドを実装してはじめて通信はしるよう
rtn.subscribe({
next:(response:HttpResponse<Item>) => {
console.log('subscribe next')
console.log(response)
//「title」が存在しなくてもエラーにはならず[undifined]
console.log(response.body?.title)
},
error:(e)=>{
//404の時など、handleErrorの後に実行される
console.log('subscribe error')
console.log(e);
}
});
}
getItem2(){
const rtn:Observable<Item> = this.http.get<Item>(this.host+'/sample').pipe(
timeout(5000),
catchError(this.handleError)
);
rtn.subscribe({
next:(response:Item) => {
console.log('subscribe next')
console.log(response)
//「title」が存在しなくてもエラーにはならず[undifined]
console.log(response.title)
},
error:(e)=>{
//404の時など、handleErrorの後に実行される
console.log('subscribe error')
console.log(e);
}
});
}
private handleError(error: HttpErrorResponse) {
console.log('handleError');
if (error.status === 0) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
console.error(
`Backend returned code ${error.status}, body was: `, error.error);
}
// Return an observable with a user-facing error message.
return throwError(() => new Error('Something bad happened; please try again later.'));
}
}
2.CORSエラー対策
CORSエラーが発生するので以下3つのいずれかが必要
CORSについて参考サイト:
https://b1san-blog.com/post/spring/spring-cors/
①Angularでリバースプロキシ設定
下記をAngularのプロジェクトルートへ配置後、
「ng serve --proxy-config proxy.conf.json」で起動させる
proxy.conf.json
{
"/api": {
"target": "http://localhost:8080/api/v1",
"pathRewrite": {
"^/api": ""
}
}
}
②SpringBootでWebConfig作成
WebConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*");
}
}
③SpringBootのControllerに@CrossOriginを付ける
AngularRestController
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin//これ
@RequestMapping("/api/v1")
public class AngularRestController {;
@GetMapping("/sample")
public String getAll() {
return "{\"title\":\"app\"}";
}
}