Write in front
This article is written in markdown format. It is the first time I wrote this. The layout may be a bit messy, and I hope you can forgive it.
It mainly writes that use Ribbon to make Restful requests, test the use of various methods, the code is relatively redundant, which is more suitable for beginners, so I mind giving it a squirt. Thank you.
premise
Note: In the article, you need to upgrade the spring-boot-starter-parent version to 1.5.9.REALEASE or above (the 1.3.7.RELEASE version does not have these annotations)
Suggestion: Each microservice application has its own spring-boot-maven-plugin and maven-compiler-plugin and specifies that the jdk compiled version is 1.8. The specification method is as follows: add it in pom.xml
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Test project construction
Eureka Registration Center: Reference Registration Center Establishment Service Provider: Reference Registration Service Provider
ribbon consumers: Reference service discovery and consumption
After the project is built, remember to follow the configuration hosts file mentioned in these tutorials.
In order to prevent the RequestMapping in the project from being the same, we will delete all controller classes (service providers and consumers). Next, I will encapsulate each restful method into a class for everyone to view
Get Request
getForEntity: This method has three overload forms, namely:
Note: This method returns a wrapper object ResponseEntity<T> where T is the responseType passed in type. If you want to get the return type, you need to use the getBody() method of this wrapper object.
getForObject: This method also has three overloaded forms, which is the same as the getForEntity method:
Note: The object type returned by this method is responseType passed in type
For the convenience of testing, the same User class is provided in the service provider and the service consumer respectively for convenience of testing
package com.cnblogs.hellxz;/** * pojo for testing */public class User { private String name; private String sex; private String phone; public User(){} public User(String name, String sex, String phone) { this.name = name; this.sex = sex; this.phone = phone; } public String toString(){ return "user:{" +"name: " + name + ", " +"sex: " + sex + ", " +"phone: " + phone +" }"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; }}Below we create a GetRequestController at the service provider
package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.*;/** * @Author : Hellxz * @Description: Service Provider* @Date : 2018/4/18 11:36 */@RestControllerpublic class GetRequestController { @Autowired private DiscoveryClient client; //Inject discovery client private final Logger logger = Logger.getLogger(GetRequestController.class); /** * go straight test */ @GetMapping(value = "/hello") public String hello(){ //Get the service instance, and the function is to display the effect of the console later ServiceInstance serviceInstance = client.getLocalServiceInstance(); logger.info("/hello host:"+serviceInstance.getHost()+" service_id:" +serviceInstance.getServiceId()); return "hello"; } /** * parameter test */ @GetMapping(value = "/greet/{dd}") public String greet(@PathVariable String dd){ ServiceInstance serviceInstance = client.getLocalServiceInstance(); logger.info("/hello host:"+serviceInstance.getHost()+" service_id:" +serviceInstance.getServiceId()); return "hello "+dd; } /** * Return the test object*/ @GetMapping("/user") public User getUser(){ ServiceInstance serviceInstance = client.getLocalServiceInstance(); logger.info("/user "+serviceInstance.getHost()+" port:"+serviceInstance.getPort()+" serviceInstanceid:"+serviceInstance.getServiceId()); return new User("hellxz","male", "123456789"); } /** * Return the object according to the name, and the database search operation is simulated here*/ @GetMapping("/user/{name}") public User getUserSelect(@PathVariable String name){ ServiceInstance serviceInstance = client.getLocalServiceInstance(); logger.info("/user "+serviceInstance.getHost()+" port:"+serviceInstance.getPort()+" serviceInstanceid:"+serviceInstance.getServiceId()); if(name.isEmpty()){ return new User(); }else if(name.equals("hellxz")){ return new User("hellxz","male", "123456789"); }else{ return new User("Random User","male", "987654321"); } }}Next we create a GetRequestController in the Service Consumer Project
package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;import java.util.HashMap;import java.util.Map;/** * @Author : Hellxz * @Description: ribbon consumer application Controller, get request* @Date : 2018/4/16 15:54 */@RestControllerpublic class GetRequestController { private Logger logger = Logger.getLogger(GetRequestController.class); @Autowired //Inject restTemplate private RestTemplate restTemplate; /** * ResponseEntity<T> getForEntity(String url, Class<T> responseType) * T getBody() The following method is the same */ @GetMapping(value="/entity/noparam") public String noParamGetForEntity(){ //Commented here because I took it out of this way because I used the interface of the straight-chain access service provider, so that the result will not be returned, and an error will be reported //return restTemplate.getForEntity("http://localhost:8080/hello",String.class).getBody(); //Use restTemplate to call the microservice interface return restTemplate.getForEntity("http://hello-service/hello", String.class).getBody(); } /** * ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) */ @GetMapping("/entity/type") public User getForEntityIdentifyByType(){ //Return the result of the specified type without passing the parameter ResponseEntity<User> entity = restTemplate.getForEntity("http://hello-service/user", User.class); User body = entity.getBody(); logger.info("user:"+body); return body; //The above can be abbreviated as // return restTemplate.getForEntity("http://hello-service/user", User.class).getBody(); } /** * ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) * Use placeholders to replace the parameters, and use the String.format method internally to implement */ @GetMapping(value="/entity") //If the received parameter is used without using it? If so, use @PathVariable, otherwise use @RequestParam public String getForEntityByQuestionMarkParam(@RequestParam("name") String name){ //The main tests the getEntity method, here the test directly passes the parameter return restTemplate.getForEntity("http://hello-service/greet/{1}", String.class, name).getBody(); } /** * The getForEntity method will extract the map internally, and the value of the placeholder key is backfill into the url as a parameter* ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) */ @GetMapping(value="/entity/map/{name}") //If the received parameter is used, use @PathVariable, otherwise use @RequestParam public String getForEntityByMap(@PathVariable("name") String name){ //The main tests the getEntity method, here tests the map parameter Map<String, String> reqMap = new HashMap(); reqMap.put("name",name); return restTemplate.getForEntity("http://hello-service/greet/{name}", String.class,reqMap).getBody(); } /** * ResponseEntity<T> getForObject(URI url, Class<T> responseType) */ @GetMapping("/entity/uri") public String getForEntityByURI(){ //Use uri to pass arguments and access UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/greet/{name}").build().expand("laozhang").encode(); URI uri = uriComponents.toUri(); return restTemplate.getForEntity(uri, String.class).getBody(); } /** * T getForObject(String url, Class<T> responseType) */ @GetMapping("/object") public User getForObjectWithNoParam(){ //Compared with the getForEntity method, getting the object can omit calling getBody return restTemplate.getForObject("http://hello-service/user", User.class); } /** * T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) */ @GetMapping("/object/map") public User getForObjectByMap(){ //Use map to pass the parameter Map<String, String> paramMap = new HashMap<>(); paramMap.put("name","hellxz"); return restTemplate.getForObject("http://hello-service/user", User.class, paramMap); } /** * T getForObject(String url, Class<T> responseType, Object... uriVariables) */ @GetMapping("/object/param/{name}") public User getForObjectByParam(@PathVariable String name){ return restTemplate.getForObject("http://hello-service/user/{name}",User.class, name); } /** * T getForObject(URI url, Class<T> responseType) */ @GetMapping("/object/uri/{name}") public User getForObjectByURI(@PathVariable String name){ UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/user/{name}") .build().expand(name).encode(); URI uri = uriComponents.toUri(); return restTemplate.getForObject(uri,User.class); }}First start the registration center, and then test it by accessing the interface provided by the consumer. These are all actually operated by me, so I won’t write a test here.
Post request
Both post request and get request have *ForEntity and *ForObject methods, where the parameter list is somewhat different. In addition to these two methods, there is also a postForLocation method, where postForLocation submits the resource as a post request and returns the URI of the new resource.
postForEntity: There are three overloaded forms of this method, namely:
Note: This method returns a wrapper object ResponseEntity<T> where T is the responseType passed in type. If you want to get the return type, you need to use the getBody() method of this wrapper object.
postForObject: This method also has three overload forms, which is the same as the postForEntity method:
Note: The object type returned by this method is responseType passed in type
postForLocation: There are also three overload forms in this method, namely:
Note: This method returns the URI of the new resource. The difference between getForEntity, getForObject, postForEntity, and postForObject methods is that there is no need to specify the return type in this method, because the return type is the URI. It still requires a placeholder to pass arguments through Object... uriVariables, Map<String, ?> uriVariables. See the postForEntity part of the code.
In the previous way, we created PostRequestControllers in projects that provide service providers and consumers respectively.
The following service PostRequestController code is as follows:
package com.shunneng.springcloudhelloworld;import org.apache.log4j.Logger;import org.springframework.web.bind.annotation.*;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;/** * @Author : Hellxz * @Description: * @Date : 2018/4/18 10:21 */@RestControllerpublic class PostRequestController { private Logger logger = Logger.getLogger(PostRequestController.class); /** * Receive an object and return it back. The postForEntity/postForObject method is common*/ @PostMapping("/user") public User returnUserByPost(@RequestBody User user){ logger.info("/use interface"+user); if(user == null) return new User("This is an empty object","",""); return user; } /** * Test the parameters of the PostForEntity method, you can directly judge the output */ @PostMapping("/user/{str}") public User returnUserByPost(@PathVariable String str, @RequestBody User user){ logger.info("/user/someparam Interface parameter name: "+str +" "+user); if(user == null) return new User("This is an empty object","",""); return user; } /** * Return URI for the postForLocation method */ @PostMapping("/location") public URI returnURI(@RequestBody User user){ //Simulate a url here, the real resource location may not be here UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/location") .build().expand(user).encode(); URI toUri = uriComponents.toUri(); //I don't know what the problem is here. It's obviously generated, but it seems that logger.info("/location uri:"+toUri); return toUri; }}Consumer PostRequestController code:
package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import org.springframework.web.util.UriComponents;import org.springframework.web.util.UriComponentsBuilder;import java.net.URI;/** * @Author : Hellxz * @Description: Ribbon consumer post request controller * @Date : 2018/4/18 9:47 */@RestControllerpublic class PostRequestController { private Logger logger = Logger.getLogger(PostRequestController.class); @Autowired private RestTemplate restTemplate; /** * ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType) * The parameter url is not mentioned. If the Object request is not an HttpEntity object, it will be automatically converted to an HttpEntity object and treated as a complete body; * If it is an HttpEntity object, it will be processed directly as a body and contains the header content. * I won't talk about the rewrite method below. The usage method is roughly the same as getForEntity. If it is just a simple post object, then use the method without Object...variables or Map variables. * postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables) * postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) * * Here we will talk about the pitfalls I encountered in detail: * 1. The Object...variables and Map variables on the last edge of several other overloaded methods both operate on the previous url, * That is to say, use placeholders to pass parameters in the url requested by the post, and if no placeholders are used in the url, then these last passed parameters are invalid! * 2. If the object request object in the method has the same type as the service provider's receiving parameter, the service provider only needs to use @RequestBody to receive parameters. * 3. If both are used, this is more interesting. You need to receive parameters in the uri through @PathVariable annotation, and you also need @RequestBody to receive objects or RequestParam to receive parameters according to fields! * 4. If you report an error, please take a closer look at the three items I wrote above and pay attention to the use of the service provider's parameters and annotations. */ @PostMapping("/entity") public User postForEntity(){ User user = new User("hellxz1","1","678912345"); ResponseEntity<User> entity = restTemplate.postForEntity("http://hello-service/user/{str}", user, User.class, "test parameters"); User body = entity.getBody(); //All restTemplate.*ForEntity methods are wrapper classes, and body is the return type object return body; } /** * Passing parameters with URI, the test results will be displayed in the service provider's terminal* ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) */ @PostMapping("/entity/uri") public User postForEntityByURI(){ User user = new User("Lao Zhang","1","678912345"); // Here we just convert the url to a URI, and there is no parameter added UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://hello-service/user") .build().encode(); URI toUri = uriComponents.toUri(); //Use user to pass the parameter User object = restTemplate.postForObject(toUri, user, User.class); return object; } /** * When testing the postForObject method here, the parameters that need to be paid attention to are as described in the above method. The difference is that you do not need getBody, so I will not elaborate here* postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) * postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) * postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) */ @PostMapping("/object") public User postForObject(){ User user = new User("hellxz2","1","123654987"); // Here url passes 1 to call an interface in the server project User responseBody = restTemplate.postForObject("http://hello-service/user/1", user, User.class); return responseBody; } /** * There is another type of post request: postForLocation. There are also three overloads here. In addition to not specifying the return type, the usage is the same, and the return type is all URI, so I won't describe it * postForLocation(String url, Object request, Object... uriVariables) * postForLocation(String url, Object request, Map<String, ?> uriVariables) * postForLocation(URI url, Object request) */ @PostMapping("/location") public URI postForLocation(){ User user = new User("hellxz3","1","987654321"); URI uri = restTemplate.postForLocation("http://hello-service/location", user); //I don't know why it is empty. This method is for reference only. If I know what the situation is, I will come back to change logger.info("/location uri:"+uri); return uri; }}Put request &&Delete request
The put request is simpler than the get and post request methods. There is no need to specify the return type of the put request, and of course there is no return value. It is also three types of overloads, which are basically the same as the ones written before. I don’t want to say more here. Both the delete request and the put request have no return value. It doesn’t matter if you write it specifically here. The methods of these two requests are listed separately. The code is written in a class.
The put request method is as follows:
The delete request method is as follows:
Add PutAndDeleteRequestController to the provider project, the code is as follows
package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.web.bind.annotation.*;/** * @Author : Hellxz * @Description: Service provider put&delete request controller * @Date : 2018/4/19 14:11 */@RestControllerpublic class PutAndDeleteRequestController { private Logger logger = Logger.getLogger(PutAndDeleteRequestController.class); @PutMapping("/put") public void put(@RequestBody User user){ logger.info("/put "+user); } @DeleteMapping("/delete/{id}") public void delete(@PathVariable Long id){ logger.info("/delete id:"+id); }}Add PutAndDeleteRequestController to the provider project, the code is as follows
package com.cnblogs.hellxz;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;/** * @Author : Hellxz * @Description: put request, delete request, overloaded parameters are basically the same as the above demo, and will not be listed * @Date : 2018/4/19 13:43 */@RestControllerpublic class PutRequestController { private Logger logger = Logger.getLogger(PostRequestController.class); @Autowired private RestTemplate restTemplate; /** * put request example, generally put requests are mostly used as modification*/ @PutMapping("/put") public void put(@RequestBody User user){ restTemplate.put("http://hello-service/put",user); } /** * delete request example*/ @DeleteMapping("/del/{id}") public void delete(@PathVariable Long id){ restTemplate.delete("http://hello-service/delete/{1}", id); }}Conclusion
This blog post is written using markdown. I don’t know how to add serial numbers and fold code functions to the code block for the first time. This may not be a good article, but I have been writing this blog post for almost two days. If you have any good suggestions, please feel free to comment and exchange.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.