Spring boot restful API
Restful API expresses CRUD operations through HTTP, the following is a set of Restful APIs to add, delete, modify and list FX currency values.
URL | HTTP Method | function |
/fx | POST | list all the FX values |
/fx/{id} | GET | get FX values |
/fx/{id} | DELETE | delete FX |
/fx/{id} | PUT | update FX |
The URL is only the way to identify the resource, and the specific behavior is specified by the HTTP method
Now let’s take a look at how to implement the above interface
@RestController
@RequestMapping("/rest")
public class FxRestController {
@Autowired
private FxService fxService;
@RequestMapping(value = "/fx", method = POST, produces = "application/json")
public WebResponse<Map<String, Object>> saveFx(@RequestBody Fx fx) {
fx.setUserId(1L);
fxService.saveFx(fx);
Map<String, Object> ret = new HashMap<>();
ret.put("id", fx.getId());
WebResponse<Map<String, Object>> response = WebResponse.getSuccessResponse(ret);
return response;
}
@RequestMapping(value = "/fx/{id}", method = DELETE, produces = "application/json")
public WebResponse<?> deleteFx(@PathVariable Long id) {
Fx fx = fxService.getById(id);
fx.setStatus(-1);
fxService.updateFx(fx);
WebResponse<Object> response = WebResponse.getSuccessResponse(null);
return response;
}
@RequestMapping(value = "/fx/{id}", method = PUT, produces = "application/json")
public WebResponse<Object> updateFx(@PathVariable Long id, @RequestBody Fx fx) {
fx.setId(id);
fxService.updateFx(fx);
WebResponse<Object> response = WebResponse.getSuccessResponse(null);
return response;
}
@RequestMapping(value = "/fx/{id}", method = GET, produces = "application/json")
public WebResponse<Article> getFx(@PathVariable Long id) {
Fx fx = fxService.getById(id);
WebResponse<Fx> response = WebResponse.getSuccessResponse(fx);
return response;
}
}
Let’s analyze this code again.
- We use the @RestController instead of @Controller, but this is also not provided by Spring boot, but provided in Spring MVC4
- There are three URL mappings in this class that are the same, they are all /fx/{id}, which is not allowed in the class @Controller.
- The @PathVariable is also provided by Spring MVC
So it seems that this code still has nothing to do with Spring boot. Spring boot only provides automatic configuration functions.
Let’s send some http requests with postman to see the results.
Finding the nearby people/vehicle through latitude and longitude
Now that we know the latitude and longitude of the user’s current location and the range we are going to search, i.e. a center point and radius, the maximum and minimum values of longitude and latitude.
First declare a function to calculate the range of latitude and longitude
/**
* Calculate the range based on the latitude, longitude and radius
* @param string $latitude
* @param String $longitude
* @param float $radius
* @return Array
*/
private function calcScope($latitude, $longitude, $radius) {
$degree = (24901 * 1609) / 360.0;
$dpmLatitude = 1 / $degree;
$radiusLatitude = $dpmLatitude * $radius;
$minLatitude = $latitude - $radiusLatitude; // min latitude
$maxLatitude = $latitude + $radiusLatitude; // max latitude
$mpdLongitude = $degree * cos($latitude * (PI / 180));
$dpmLongitude = 1 / $mpdLongitude;
$radiusLongitude = $dpmLongitude * $radius;
$minLongitude = $longitude - $radiusLongitude; // min longitude
$maxLongitude = $longitude + $radiusLongitude; // max longitude
$scope = array(
'minLatitude' => $minLatitude,
'maxLatitude' => $maxLatitude,
'minLongitude' => $minLongitude,
'maxLongitude' => $maxLongitude
);
return $scope;
}
The returned array contains the maximum and minimum latitude and longitude that meet the conditions
Then we can find all the records that meet the conditions from the database
/**
* search those latitude, longitude are within range
* @param String $latitude
* @param String $longitude
* @param float $radius
* @return Array
*/
public function searchByLatAndLng($latitude, $longitude, $radius) {
$scope = $this->calcScope($latitude, $longitude, $radius); // get the min and max for latitude and logitude
$sql = 'SELECT id, type, latitude, longitude FROM last_location WHERE `latitude` < '.$scope['maxLatitude'].' and `latitude` > '.$scope['minLatitude'].' and `longitude` < '.$scope['maxLongitude'].' and `longitude` > '.$scope['minLongitude'];
$sth = $dbh->query($sql);
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
Now we have the result that are within the range, we could calculate the actual distance.
/**
* calculate the distance (KM)
* @param string $lat1 latitude 1
* @param String $lng1 longitude 1
* @param String $lat2 latitude 2
* @param String $lng2 longitude 2
* @return float return the distance in km
*/
public function calcDistance($lat1, $lng1, $lat2, $lng2) {
$lat1 = doubleval($lat1);
$lng1 = doubleval($lng1);
$lat2 = doubleval($lat2);
$lng2 = doubleval($lng2);
/** calculation by google */
$theta = $lng1 - $lng2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
return ($miles * 1.609344);
}
Laravel using google captcha validation
install captcha dependence with composer
composer require buzz/laravel-google-captcha
add the class interface into ‘providers’ section in config/app.php
Buzz\LaravelGoogleCaptcha\CaptchaServiceProvider
::class,
define alias into the ‘alias’ section
'GoogleCaptcha' => Buzz\LaravelGoogleCaptcha\CaptchaServiceProvider
::class,
execute command to create configuration file
php artisan vendor:publish
edit the config file accordingly in config/captcha.php
/*
* Secret key and Site key get on https://www.google.com/recaptcha
* */
return [
'secret' => env('CAPTCHA_SECRET', 'default_secret'),
'sitekey' => env('CAPTCHA_SITEKEY', 'default_sitekey'),
/**
* @var string|null Default ``null``.
* Custom with function name (example customRequestCaptcha) or class@method (example \App\CustomRequestCaptcha@custom).
* Function must be return instance, read more in repo ``https://github.com/thinhbuzz/laravel-google-captcha-examples``
*/
'request_method' => null,
'options' => [
'multiple' => false,
'lang' => app()->getLocale(),
],
'attributes' => [
'theme' => 'light'
],
];
the code to show the captcha in the form
{!! Captcha::display($attributes) !!}
Laravel Restful API
Its not difficult to create restful API with Laravel.
First create controller for handling data
php artisan make:controller api/FxInfoController --api
This will create the controller with some dummy functions index()
show()
store()
update()
destory()
Update the api/FxInfoController.php
<?php
namespace App\Http\Controllers\api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\FxInfo;
class FxInfoController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return response()->json(FxInfo::all(), 200);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$fxInfo = UserInfo::create($request->all());
return response()->json($fxInfo, 201);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(FxInfo $fxInfo)
{
return response()->json($fxInfo, 200);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, FxInfo $fxInfo)
{
$fxInfo->update($request->all());
return response()->json($fxInfo, 200);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(FxInfo $fxInfo)
{
$fxInfo->delete();
return response()->json(null, 204);
}
}
Now update the routes/api.php to define where to go
e.g. http://127.0.0.1:8000/api/fx will go to api\FxInfoController.php index() function
Route::get(‘fx’, ‘api\FxInfoController@index’);
Route::get(‘fx/{fxInfo}’, ‘api\FxInfoController@show’);
Route::post(‘fx’, ‘api\FxInfoController@store’);
Route::put(‘fx/{fxInfo}’, ‘api\FxInfoController@update’);
Route::delete(‘fx/{fxInfo}’, ‘api\FxInfoController@destroy’);
A simple Restful API is done, we can try it with Postman