2022年3月6日 星期日

使用RestTemplate請求Token

參考了幾篇文章, 直接拿來用, 然後就.....掛掉

真是不靠譜, 還是自己寫一篇好

根據下列這篇

https://www.baeldung.com/spring-resttemplate-post-json

基本上傳過去的內容是可以用Json物件

不過~他其實也可以傳自定義物件

所以我們就拿自定義物件來做示範


這是要傳過去的物件


public class JwtUserExternal {
	
	private String account;
	private String pwd;
	...
}

在開始的地方先注入


	@Autowired
	RestTemplate restTemplate;

要在Config也加入Bean就是, 不然會報java.lang.IllegalStateException: Failed to load ApplicationContext錯誤


	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

因為URI是從資料庫取出來, 我們化名為Target

然後從Target對象中取出帳號密碼, 生出JwtUserExternal物件

然後就~call sendRequestForToken function, 把Url和物件傳過去, 取得Token


	public String getToken(String LabId) {
		Target target = targetRepo.findById(Id);
		if (target == null) {
			throw new ICUmodelJwtException(HttpStatus.NOT_FOUND, "patientExamin not found");
		}
		JwtUserExternal jwtUser = new JwtUserExternal(target.getTokenId(), target.getTokenPassword());
		String token = sendRequestForToken(patientExamine.getTokenUrl(), jwtUser);
		return token;
	}

打對方API細節

這裡先生出HttpHeader, 再用它和傳送物件生出HttpEntity為request

然後使用restTemplate.postForObject(url, request, String.class)

將回傳值用使用ObjectMapper轉成JsonNode

目前回傳格式是這樣

{
    "CODE""OK",
    "TOKEN""eyJhbGciOxxxxxxxxx"
}

因此就root.path("TOKEN").asText()就能拿出Token


	public String sendRequestForToken(String url, JwtUserExternal requestObject) {
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<jwtuserexternal> request = new HttpEntity<jwtuserexternal>(requestObject, headers);
			String personResultAsJsonStr = restTemplate.postForObject(url, request, String.class);
			ObjectMapper objectMapper = new ObjectMapper();
			JsonNode root = objectMapper.readTree(personResultAsJsonStr);
			return root.path("TOKEN").asText();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	

完整的類別如下



@Service
public class JwtLogin {

	@Autowired
	RestTemplate restTemplate;

	@Autowired
	TargetRepo targetRepo;

	private String targetId;

	public String getToken() {
		String token = getToken(this.getLabId());
		return token;
	}

	public String getToken(String id) {
		Target target = targetRepo.findByTargetId(id);
		if (target == null) {
			throw new ICUmodelJwtException(HttpStatus.NOT_FOUND, "target not found");
		}
		JwtUserExternal jwtUser = new JwtUserExternal(target.getTokenId(), target.getTokenPassword());
		String token = sendRequestForToken(target.getTokenUrl(), jwtUser);
		return token;
	}

	public String sendRequestForToken(String url, JwtUserExternal requestObject) {
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<JwtUserExternal> request = new HttpEntity<JwtUserExternal>(requestObject, headers);
			String personResultAsJsonStr = restTemplate.postForObject(url, request, String.class);
			ObjectMapper objectMapper = new ObjectMapper();
			JsonNode root = objectMapper.readTree(personResultAsJsonStr);
			return root.path("TOKEN").asText();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public String getTargetId() {
		return targetId;
	}

	public void setTargetId(String targetId) {
		this.targetId = targetId;
	}

}

重構以上程式碼

差異部分,直接傳Json物件過去

重構的點是因為, 有可能來源來自於不同Table

我們對前面邏輯, 開放新增方法, 可以自行新增將JwtUserExternal set進來

也就是如果他從其他來源來, 可以新增一個類似setTargetId, 只要將JwtUserExternal設到成員變數就可

對後面邏輯封閉, 傳參JwtUserExternal類讓他可以打API, 來取回Token

新增方法上符合開閉原則

JwtUserExternal類別


public class JwtUserExternal {
	
	private String account;
	private String pwd;
	private String url;
	...
		
}

主程式


@Service
public class JwtLogin {

	@Autowired
	RestTemplate restTemplate;

	@Autowired
	PatientExamineRepo patientExamineRepo;

	private JwtUserExternal jwtUserExternal;
	

	public String getToken() {
		String token = sendRequestForToken(this.getJwtUserExternal());
		return token;
	}
	
	public void setTargetId(String targetId) {
		Target target = targetRepo.findByTargetId(targetId);
		if (target == null) {
			throw new ICUmodelJwtException(HttpStatus.NOT_FOUND, "target not found");
		}
		this.setJwtUserExternal(new JwtUserExternal(
						target.getTokenId(),
						target.getTokenPassword(),
						target.getTokenUrl())
				);
	}

	public String sendRequestForToken(JwtUserExternal jwtUser) {
		try {
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			JSONObject requestObject = new JSONObject();
			requestObject.put("account", jwtUser.getAccount());
			requestObject.put("pwd", jwtUser.getPwd());
			HttpEntity<String> request = new HttpEntity<String> (requestObject.toString(), headers);
			String personResultAsJsonStr = restTemplate.postForObject(jwtUser.getUrl(), request, String.class);
			ObjectMapper objectMapper = new ObjectMapper();
			JsonNode root = objectMapper.readTree(personResultAsJsonStr);
			return root.path("TOKEN").asText();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public JwtUserExternal getJwtUserExternal() {
		return jwtUserExternal;
	}

	public void setJwtUserExternal(JwtUserExternal jwtUserExternal) {
		this.jwtUserExternal = jwtUserExternal;
	}	

}

沒有留言:

張貼留言

[leetcode] [KMP] KMP

ABCDABD... ABCDABF... 簡單的說, 傳統解兩字串匹配部分 可能會來個雙迴圈, 哀個比對, 當不匹配的時候, 會將下方列再後移1位 然後不匹配再後移 然而 如果像上放已經有4個屬於匹配的字串, 她就應該直接往後移四位來匹配, 而不是只移動1位 隱藏的思維是, 當...