1. A brief description of the restful
Rest is a design style, a set of constraints and principles, and the rest-style architecture is called the RESTful architecture, the resource is the core of the restful, a good restful architecture, through the URL can clearly understand its corresponding operation and requirements is what, namely
1. Locate resources by URL, such as:
Com.mobin/api/v1/shenzhen/subways//Get Shenzhen Metro list
Com.mobin/api/v1/shenzhen/schools//Get a list of Shenzhen schools
2. HTTP Description operation
Get: Get Resources
POST: Creating a Resource
PUT: Updating resources
Delete: Deleting a resource
Such as:
Get COM.MOBIN/API/V1/SHENZHEN/SUBWAYS/1: Get metro information with ID 1
The requested resources are usually returned to the client in JSON or XML, and the restful architecture simply provides a restful API on the sever side that can be shared on the Web, IOS, Android
API design is a very important thing, you can refer to the GitHub API design specifications
2. Springboot Integrated MyBatis
1. Put Xxxmapper.xml and sqlmapconfig.xml into the resource corresponding directory
2. application.properties loading MyBatis configuration file and configuration data source
1 # #application. Properties2 #加载mybatis配置文件3Mybatis.mapper-locations = Classpath:mapper/*Mapper.xml4 mybatis.config-location = Classpath:mapper/config/sqlmapconfig.xml5 ?6 #指定别名7 mybatis.type-aliases-package = com.mobin.entity8 ?9 #数据源Ten Spring.datasource.url = jdbc:postgresql://localhost:5432/xxx One spring.datasource.driver-class-name = Org.postgresql.Driver A spring.datasource.username = Postgres - Spring.datasource.password = xxxx
MyBatis 3 After the official provided a specific API to support dynamic SQL, you can use the annotated +java code to replace the XML, but the complex SQL statement is the way to go XML, XML is more intuitive (in fact, disgusting), the way the annotations to the code intrusion is too serious, You will also need to recompile after the modification.
3. Log Configuration
Spring boot The default log frame is Logback, is configured to be quite friendly with better performance, and can be filtered at different levels for the log of the specified service and does not affect the level of other service logs
1. Console Log Configuration
2. Development, test, production environment configuration
1# #logbcak-Spring.xml2<?xml version= "1.0" encoding= "UTF-8"?>3<configuration debug= "false" >4<contextName>${appname}</contextName>5<!--console Log configuration-6<appender name= "STDOUT"class= "Ch.qos.logback.core.ConsoleAppender" >7<encoderclass= "Ch.qos.logback.classic.encoder.PatternLayoutEncoder" >8<pattern>%d{yyyy-mm-dd HH:mm:ss. SSS} [%thread]%-5level%logger{50}-%msg%n</pattern>9</encoder>Ten</appender> One ? A<appender name= "Fileprod"class= "Ch.qos.logback.core.rolling.RollingFileAppender" > -<rollingpolicyclass= "Ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > -<FileNamePattern>SpringBootRESTful.%d{yyyy-MM-dd}.log</FileNamePattern> the<!--log retention days-- -<MaxHistory>20</MaxHistory> -</rollingPolicy> -<encoderclass= "Ch.qos.logback.classic.encoder.PatternLayoutEncoder" > +<pattern>%d{yyyy-mm-dd HH:mm:ss. SSS} [%thread]%-5level%logger{50}-%msg%n</pattern> -</encoder> +</appender> A ? at<appender name= "Filetest"class= "Ch.qos.logback.core.rolling.RollingFileAppender" > -<rollingpolicyclass= "Ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > -<filenamepattern>test. Springbootrestful.%d{yyyy-mm-dd}.log</filenamepattern> -<MaxHistory>20</MaxHistory> -</rollingPolicy> -<encoderclass= "Ch.qos.logback.classic.encoder.PatternLayoutEncoder" > in<pattern>%d{yyyy-mm-dd HH:mm:ss. SSS} [%thread]%-5level%logger{50}-%msg%n</pattern> -</encoder> to</appender> + ? -< log configuration for!--development environment-- the<springprofile name= "Dev" > *<!--the development environment typically tests the specified package or class- $<logger name= "Com.mobin.dao" level= "DEBUG" >Panax Notoginseng<appender-ref ref= "STDOUT"/> -</logger> the<root level= "INFO" > +<appender-ref ref= "STDOUT"/> A</root> the</springProfile> + ? -< log configuration for!--test environment-- $<springprofile name= "Test" > $<root level= "DEBUG" > -<appender-ref ref= "Filetest"/> -<appender-ref ref= "STDOUT"/> the</root> -</springProfile>Wuyi ? the< log configuration!--production environment-- -<springprofile name= "prod" > Wu<root level= "INFO" > -<appender-ref ref= "FILEINFO"/> About<appender-ref ref= "STDOUT"/> $</root> -</springProfile> -</configuration>
4. Exception handling
4.1 in the API design specification, the handling of exceptions is at least
1. returns the corresponding error code
&NBSP; 2. returns the appropriate error description
3. corresponding resource module
4.2 Using @restcontrolleradvice to define global exception handling
@RestControllerAdvice is a new feature after Spring 4.3, which is equivalent to @controlleradvice+ Responsebody, so use @restcontrolleradvice to return the error message in JSON format
1. Custom Exception class
1 # #com. Mobin.exception.EntityNotFoundException 2 // This exception is thrown when the requested resource does not exist 3 Public class extends runtimeexception{4 Public entitynotfoundexception (String mes) {5 Super (MES); 6 }7 }
2. Defining Global Exception classes
1 # #com. Mobin.exception.GlobalExceptionHadlerActice2 @RestControllerAdvice3 Public classGlobalexceptionhadleractice {4 Private Static Final LongSerialversionuid = 1L;5@ExceptionHandler (value = entitynotfoundexception.class)6 Publicerrormessage entitynotfoundexception (httpservletrequest request, Exception e) {7ErrorMessage errormessage =Newerrormessage ();8 Errormessage.setstatus (HttpStatus.NOT_FOUND.value ());9 Errormessage.setmessage (E.getlocalizedmessage ());Ten Errormessage.seturl (Request.getrequesturl (). toString ()); One returnerrormessage; A } -}
ErrorMessage is a custom entity class that contains Statuscode,message and URL fields.
3. The corresponding Request method
1 # # Com.mobin.controller.SubwayController2@RequestMapping (value= "/{id}", method =requestmethod.get)3 PublicSubwayresult<subway>Getsubwaybyid (@PathVariable Integer id) {4subwayresult<subway> result =NewSubwayresult ();5Subway Subway =Subwayservice.findsubwaybyid (ID);6 if(Subway = =NULL){7 Throw NewEntitynotfoundexception ("Resource does not exist");8 }9 Result.setstatus (HttpStatus.OK.value ());Ten Result.setdata (subway); One returnresult; A}
4. Test with Curl
1 mobin:~ mobin$ curl-xget-w "\ n" ' localhost:8089/api/subways/1999 '2{3 " Message ":" Resource does not exist ",4 " status ": 404,5 " url ":" http://localhost:8089/ api/subways/1999 "6 }
5. Using Fastjson
1. Introduction of Fastjson dependency
2. customizing Webmvcconfigurer and inheriting Webmvcconfigureradapter
3. overriding the Configuremessageconverters method
4. Custom Configuration Fastjsonconfig
5. Add Fastjsonhttpmessageconverter to Httpmessageconverter
Corresponding Code:
1 # #com. Mobin.config.WebMvcConfigurer2 @Configuration3 Public classWebmvcconfigurerextendswebmvcconfigureradapter{4 @Override5 Public voidConfiguremessageconverters (listconverters) {6Fastjsonhttpmessageconverter converter =NewFastjsonhttpmessageconverter ();7Fastjsonconfig config =Newfastjsonconfig ();8 config.setserializerfeatures (Serializerfeature.writenulllistasempty,9 Serializerfeature.writemapnullvalue,Ten Serializerfeature.writenullstringasempty, One Serializerfeature.writenullbooleanasfalse, A Serializerfeature.prettyformat); -Converter.setdateformat ("Yyyy-mm-dd HH:mm:ss"); - converter.setfastjsonconfig (config); the Converters.add (converter); - - } -}
SerializerFeature.WriteNullListAsEmpty:List Type field is null when output [] rather than null
Serializerfeature.writemapnullvalue: Show Empty fields
Serializerfeature.writenullstringasempty: String Type field is null time output "" rather than null
SerializerFeature.WriteNullBooleanAsFalse:Boolean Type field is null when output is false and null
Serializerfeature.prettyformat: Beautify the JSON output, otherwise it will be output as an entire line
solve the problem of returning JSON display garbled in the browser (refer to From: http://blog.csdn.net/kingboyworld/article/details/70068676)
# #application. Propertiesspring.http.encoding.charset=utf-8spring.http.encoding.enable= TrueSpring.http.encoding.force=true
6. Paging using Pagehelper
Paging is using the Pagehelper plug-in, the basic principle is to intercept the SQL statements between executor and mappedstatement and add the corresponding paging operation to the SQL to be passed to mappedstatement. The plug-in supports single table and multi-table paging, easy to use, simply add a distribution code before the SQL execution statement (usually in the server layer), think if it is manually set the SQL statement of limit and offset, the paging scene once more is particularly disgusting, Even with the reverse engineering of MyBatis.
1. introduce the spring boot corresponding pagehelper dependency
2. application.properties Configuration Pagehelper
3. add pagination code before the specified SQL statement
1 # #application. Properties 2 #指定数据库方言 3 pagehelper.helperdialect=PostgreSQL4 #pageNum <=0 O'Clock returns the first page of data, Pagenum returns the last page of data when it exceeds the total number of pages 5 pagehelper.reasonable=true
Corresponding Code:
1 # #com. Mobin.service.impl.SubwayServiceImpl 2 Public List<subway> findsubways (int pagenum,int pageSize) {3 // the third parameter, Fales, indicates that the table is not count-operated 4 Pagehelper.startpage (Pagenum,pagesize,false); 5 return subwaymapper.findsubways (); 6 }
Project Address:
Https://github.com/MOBIN-F/SpringBootRESTful
Resources:
GitHub API
How to use @RestControllerAdvice for handling Exception with RESTFULAPI
Pagehelper How to use
Serializerfeature use of the detailed
Logback Related Configurations
The practice of RESTful API based on spring boot (i)