Angular Stock上市个股日成交(一)(Day27)

今天我们要开始实作最後一个页面了,这个页面功能是可以显示上市个股日成交的资讯

还记得我们在Angular视觉化套件(Day19)所引入的ZingChart吗?

在最後的几天我们会透过携带token的方式,向StockAPI请求资料,并将资料利用ZingChart呈现出来。


现在让我们先从httpServe开始吧

还记得我们取得上市个股日是用get方法吗?
因此我们要新增一个get方法


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { APIReturnObject } from '../model/APIReturnObject';
import { Observable } from 'rxjs';
import { HttpHeaders } from '@angular/common/http';
@Injectable({
  providedIn: 'root'
})
export class HttpService {
  private rootUrl = 'http://localhost:8080/';
  constructor(private http: HttpClient) { }

  getPosts(params: object, webUrl: string): Observable<APIReturnObject> {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'responseType': 'json'
    });
    const options = {
      headers
    };
    return this.http.post<APIReturnObject>(this.rootUrl + webUrl, params, options);
  }

#新增get方法
  getGets(token: string, webUrl: string): Observable<APIReturnObject> {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'responseType': 'json',
      'Authorization': 'Bearer ' + token
    });
    return this.http.get<APIReturnObject>(this.rootUrl + webUrl,{headers:headers});
  }
}

在这边可以看到我们把token放置在header的Authorization属性内


2021/10/13更新
新增一个 DailyTranctionStockData 的介面


export class DailyTranctionStockData {
    Code: string;
    Name: string;
    TradeVolume: number;
    TradeValue: number;
    OpeningPrice: number;
    HighestPrice: number;
    LowestPrice: number;
    ClosingPrice: number;
    Change: number;
    Transaction: number;
    constructor(
        Code: string,
        Name: string,
        TradeVolume: number,
        TradeValue: number,
        OpeningPrice: number,
        HighestPrice: number,
        LowestPrice: number,
        ClosingPrice: number,
        Change: number,
        Transaction: number
    ) {
        this.Code = Code;
        this.Name = Name;
        this.TradeVolume = TradeVolume;
        this.TradeValue = TradeValue;
        this.OpeningPrice = OpeningPrice;
        this.HighestPrice = HighestPrice;
        this.LowestPrice = LowestPrice;
        this.ClosingPrice = ClosingPrice;
        this.Change = Change;
        this.Transaction = Transaction;
    }

}


接下来我们要修改一下之前我们login.component储存进sessionStorage的值


import { Component, OnInit } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { HttpService } from '../service/http.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  title = '登入';
  account = new FormControl('', [Validators.required, Validators.maxLength(10)]); // 验证字数须大於10个字
  password = new FormControl('', [Validators.required, Validators.minLength(3)]); // 验证字数须不少於3个字
  posts: any;
  params: any;
  token: any;
  constructor(
    private httpService: HttpService,
    private router: Router,
  ) {

  }

  ngOnInit(): void {

  }

  doLogin(): void {
    this.params = {
      'account': this.account.value,
      'password': this.password.value
    }
    this.httpService.getPosts(this.params, 'user/login').subscribe(
      (response) => {
        this.posts = response;
        const data: Map<string, object> = new Map(Object.entries(response.data));
        if (data.get('token')) {
          this.token = JSON.stringify(data.get('token'));
          this.token = this.token.replace('"', ''); #把"去除掉
          sessionStorage.setItem('token', this.token);
          this.router.navigate(['index']);
        }
      },
      (error) => { console.log(error); });
  }
}

接着我们在daily-tranction-stock.component新增一个取值的方法


import { Component, OnInit } from '@angular/core';
import { HttpService } from '../service/http.service';
import { DailyTranctionStockData } from '../model/DailyTranctionStockData';

@Component({
  selector: 'app-daily-tranction-stock',
  templateUrl: './daily-tranction-stock.component.html',
  styleUrls: ['./daily-tranction-stock.component.css']
})
export class DailyTranctionStockComponent implements OnInit {
  gets: any;
  dailyTranctionStockDatas: DailyTranctionStockData[] = [];
  token = sessionStorage.getItem('token') || '';
 
  constructor(
    private httpService: HttpService
  ) { }

  ngOnInit(): void {
	#一载入页面就发送请求
    this.httpService.getGets(this.token, 'stock/search/exchange/getStockDayAll').subscribe(
      (response) => {
        this.gets = response;
        const data: Map<string, any> = new Map(Object.entries(response.data));
        this.dailyTranctionStockDatas = data.get('dailyTranctionStockDatas');
        console.log(this.dailyTranctionStockDatas) #印出值来看
      }
    )
  }

}

实际操作後的结果

https://ithelp.ithome.com.tw/upload/images/20211012/20138857CEdC0VD8qy.png


同场加码

之前AccessCrossOrigin的问题,我後来有发现一个比较好的设定方法
在每个Controller上面新增


@CrossOrigin("*")
public class UserController {

在SecurityConfig加上设定


@Override
    protected void configure(HttpSecurity http) throws Exception {
    	http
    		.authorizeRequests()
    		.antMatchers("/user/create").hasAuthority("ADMIN") //管理员可以新增使用者资料
    		.antMatchers("/user/login").permitAll()
    		.antMatchers("/user/search/**").hasAnyAuthority("ADMIN","NORMAL") //取得用户资料
    		.antMatchers("/stock/search/**").hasAnyAuthority("ADMIN","NORMAL") //取得股市资料
    		.and()
    		.addFilterBefore(jWTCheckFilter, UsernamePasswordAuthenticationFilter.class)
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    		.and()
    		.csrf().disable()
    		.cors();
    }

这样就可以避免Access-Control-Allow-Origin的问题了

那今天先到这里,明天继续罗~!

参考资料
使用 HTTP 与後端服务进行通讯


<<:  路由把关者- Navigation Guards

>>:  [进阶指南] 不使用 JSX 开发 React( Day28 )

Day 27-如何测试 terraform 之二:自动化测试写起来辛苦,但跑起来就是一个爽

本章介绍如何使用 terratest 为 terraform 准备整合测试 课程内容与代码会放在 G...

[Day17]Love Calculator

上一篇介绍了Basically Speaking,这题有用到比较常见的写法,Integer.pars...

Day28-介接 API(番外篇 III)Dialogflow ES 之 Fulfillment 与 Events

大家好~ 今天会用实作的方式去认识 Dialogflow ES 的 Fulfillment 与 Ev...

30-26 之 DDD 战略设计 2 - 实作方法之 Event Storm

事件风暴 Event Storm 事件风暴 : 理解、访谈需求 目的 : 将商业流程视觉化,找出核心...

[Day12] 从 function 谈变数的 Scope

说到 function ,又要回头来谈变数在 function 的 scope(作用域) 先宣告一个...