Spring Boot End Point that generates a string response and displaying that response in a Angular Application

不羁岁月 提交于 2020-01-25 06:55:09

问题


I hope this isn't a repost, as I did look but couldn't find.

I have a spring boot rest client that makes a call to a rest endpoint. I am using angular to consume the result of that call and pass it to the html file belonging to the component.

My Spring Boot code looks like this:

package com.terida.teridaapp;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.*;

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class TableauController {

    @RequestMapping(value = "/post", produces="text/plain")
    public String getTicketFromPost() {
        final String URL = "http://xxx.xxx.xxx.xxx/trusted";
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept((Arrays.asList(MediaType.APPLICATION_JSON)));
        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
        map.add("username", "admin");
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
        return restTemplate.exchange(URL,HttpMethod.POST,request,String.class).getBody();

    }
}

I have an angular service that looks like this:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';


@Injectable({
  providedIn: 'root'
})
export class GetTicketService {

  constructor(private http:HttpClient) { }

  ticket: any;
  url: any = "http://localhost:8100/api/post";

  public getTicket() {
    //return this.http.get("http://localhost:8100/api/post");
    //return this.http.get(this.url,{responseType: 'text'});
    //console.log(this.http.get("http://localhost:8100/api/post"));
    console.log("creating headers");
    const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
    console.log("Making a url call to: " + this.url);
    console.log("the call: " + this.http.get(this.url,{ headers, responseType: 'text'}));
    return this.http.get(this.url,{ headers, responseType: 'text'});


  }
}

and the html on the component is this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>Ticket Number: {{ticket}}</h1>>
    <h1>Message: {{message}}</h1>
</body>
</html>

I am getting an Object passed back to my view and Im not able to access the value in the response.

Any body wanna help?

Thanks


回答1:


First of all you need to perform the a call to getTicket() method, otherwise nothing will happen. I'll do it on the constructor this time.

Then, when you call http.get(), the method is returning an Observable, that you need to subscribe to. Once subscribed you can perform the operation you want with it.

https://angular.io/guide/http

Resuming this, your service should be:

  ticket: any;
  url: any = "http://localhost:8080/api/post";


  constructor(private http:HttpClient) {
    this.getTicket();
    //You can do this on the onInit of a component as well. 
   }


  public getTicket() {

    const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
    return this.http.get(this.url,  { headers, responseType: 'text' } )
      .subscribe( r =>
        { 
          this.ticket = r 
        });
  }

PS: Following the angular structure, I don't think a service should have HTML, that would be a Component, but maybe I'm wrong.




回答2:


Ok, i had a look at this and it turns out, i would much rather have json as a response than text/plain. So I modified my spring boot controller to send back json.

That takes care of some of it (id, i don't need fancy headers in my angular request).

my spring boot code looks like this:

package com.terida.teridaapp;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.*;

@RestController
@RequestMapping("/api")

public class TableauController {

    @CrossOrigin(origins = "http://localhost:4200")
    //used this as a reference
    //https://howtodoinjava.com/spring-boot2/resttemplate/spring-restful-client-resttemplate-example/
    @RequestMapping(value = "/post", produces = MediaType.APPLICATION_JSON_VALUE, method= RequestMethod.POST)
    public String getTicketFromPost() {
        final String URL = "http://15.222.0.10/trusted";
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept((Arrays.asList(MediaType.APPLICATION_JSON)));
        MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
        map.add("username", "admin");
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map,headers);
        return restTemplate.exchange(URL,HttpMethod.POST,request,String.class).getBody();

    }


}

Im getting back a json now in postman:

Content-Type application/json

Now, my angular service looks like this:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';


@Injectable({
  providedIn: 'root'
})
export class GetTicketService {

  constructor(private http:HttpClient) { }

  ticket: any;
  url: any = "http://localhost:8100/api/post";

  public getTicket() {
    /*console.log("creating headers");
    const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
    console.log("Making a url call to: " + this.url);
    console.log("the call: " + this.http.get(this.url,{ headers, responseType: 'text' as 'json'}));
    */

   const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');
   return this.http.get(this.url,  { headers} )
     .subscribe( r =>
       { 
         this.ticket = r 
       });


  }
}

Now, before i continuing working on why Im not getting a proper response into my component.html file, I have to work through this error:

in my angular browser, i get this url that is hitting my spring server:

Access to XMLHttpRequest at 'http://localhost:8100/api/post' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Duration: 20 ms
HTTP/1.1 403 Forbidden
Transfer-Encoding: chunked
Keep-Alive: timeout=60
Connection: keep-alive
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Access-Control-Request-Method, Access-Control-Request-Headers
Date: Thu, 23 Jan 2020 23:30:32 GMT

Invalid CORS request

So, before I continue, perhaps you can tell me why my @CrossOrigin annotation doesn't seem to be doing what i expect it to do?

Then Ill move on from there :)

Thanks Chris



来源:https://stackoverflow.com/questions/59886593/spring-boot-end-point-that-generates-a-string-response-and-displaying-that-respo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!