Recently, Spring Boot, MyBatis, General Mapper plug-in and PageHelper paging plug-in were used to make several small and medium-sized API projects. After doing this, I felt that this framework and tools were very comfortable to develop such projects, and the team also received good response. In the project construction and development process also summed up some small experience, to share with you.
Before developing an API project, the basics of building the project, introducing dependencies, and configuring the framework need not be mentioned, but some common classes and tools need to be packaged to speed up the development of the project. For example, unified response result encapsulation, unified exception handling, interface signature authentication, basic add, delete, change method encapsulation, basic code generation tools, and so on.
However, the next time you do a similar project, you may have to go through the above steps again, which is usually a waste of time. So, can make use of the thought of object-oriented abstraction, encapsulation, extraction of this kind of project in common packaging has become a seed project (estimated the seeds of most companies will have a lot of similar project), so the next time to develop a similar project directly on the seed project iteration, reduce meaningless repetition of work.
Features & a project structure that provides best practices, profiles, and streamlined POM
Note: Model, DAO, Service, Web, and other packages are created when code is generated using a code generator.
Unified response result encapsulation and generation tools
/ * *
-
Public class Result {private int code; private String message; private Object data; public Result setCode(ResultCode resultCode) { this.code = resultCode.code; return this; } // omit getter, setter methods} /*
-
Enumeration of response codes, */ public enum ResultCode {SUCCESS(200),// FAIL(400),// FAIL to UNAUTHORIZED(401),// Not authorized (signature error) NOT_FOUND(404),// Interface not found INTERNAL_SERVER_ERROR(500); // Server internal error
public int code;
ResultCode(int code) { this.code = code; }} / * *
-
Response result Generation tool */ public class ResultGenerator {private static final String DEFAULT_SUCCESS_MESSAGE = “SUCCESS”;
public static Result genSuccessResult() { return new Result() .setCode(ResultCode.SUCCESS) .setMessage(DEFAULT_SUCCESS_MESSAGE); }
public static Result genSuccessResult(Object data) { return new Result() .setCode(ResultCode.SUCCESS) .setMessage(DEFAULT_SUCCESS_MESSAGE) .setData(data); }
public static Result genFailResult(String message) { return new Result() .setCode(ResultCode.FAIL) .setMessage(message); }} unified exception handling public void configureHandlerExceptionResolvers exceptionResolvers (List) {exceptionResolvers. Add (new HandlerExceptionResolver() { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) { Result result = new Result(); Result.setcode (resultcode.fail).setMessage(LLDB etMessage()); if (e instanceof ServiceException) {// Service failure exceptions, such as resultcode.fail).setMessage(LLDB etMessage()); logger.info(e.getMessage()); } else if (e instanceof NoHandlerFoundException) {result.setcode (resultcode.not_found).setMessage(” interface [” + Request. GetRequestURI () + “] does not exist “); } else if (e instanceof ServletException) { result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); } else {result.setcode (resultcode.internal_server_error).setMessage(” interface [” + request.getrequesturi () + “] internal error, Please contact the administrator “); String message; if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Format (” error [%s] : %s.%s, error: %s. %s”, request.getRequestURI(), handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod().getName(), e.getMessage()); } else { message = e.getMessage(); } logger.error(message, e); } responseResult(response, result); return new ModelAndView(); }
}); Copy the code
} public interface Service {void save(T model); // Persist void save(List models); // Batch persistence void deleteById(Integer ID); Void deleteByIds(String ids); Eg: ids -> “1,2,3,4” void update(T model); // Update T findById(Integer id); Throws TooManyResultsException; // Find T findBy(String fieldName, Object value); List findByIds(String ids); List findByIds(String ids); // ids -> 1,2,3,4 List findByCondition(Condition Condition); List findAll(); Public abstract class CodeGenerator {// get all} provide CodeGenerator to generate base code. Public static void main(String[] args) {genCode(” enter table name “); } public static void genCode(String… TableNames) {for (String tableName: tableNames) {// Generate as required. genModelAndMapper(tableName); genService(tableName); genController(tableName); }}… } CodeGenerator can generate the corresponding Model, Mapper, MapperXML, Service, ServiceImpl, and Controller (POST and RESTful Controller templates are provided by default. Select as needed in the genController(tableName) method, default is pure POST), and the code template can be customized to the needs of the actual project to minimize rework. Because every company’s business is different, a few simple generic method templates are provided, mainly to provide an idea to reduce repetitive code writing. In the actual use of our company, we actually write a lot of code templates based on business abstractions.
Public void addInterceptors(InterceptorRegistry registry) {// The interface signature authenticates the interceptor. You can use Json Web tokens or better alternatives in real projects. if (!” Dev. “equals (env)) {/ / development environment to ignore signature certification registry. AddInterceptor (new HandlerInterceptorAdapter () {@ Override public Boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object Handler) throws Exception {// Validate signature Boolean pass = validateSign(request); if (pass) { return true; } else {logger.warn(” Signature authentication failed, request interface: {}, request IP: {}, request parameters: {}”, request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
Result result = new Result(); Result.setcode (resultcode.unauthorized).setmessage (" Signature authentication failed "); responseResult(response, result); return false; }}}); }Copy the code
} / * *
- A simple signature authentication, rules:
-
- Sort the request parameters in ASCII order
-
- Joining together for a = value&b = value… Such a string (without sign)
-
-
Mixed key (secret) for MD5 to obtain signature, Compare with the request signature */ private Boolean validateSign(HttpServletRequest Request) {String requestSign = request.getParameter(“sign”); / / get the request signature, such as sign = 19 e907700db7ad91318424a97c54ed57 if (StringUtils. IsEmpty (requestSign)) {return false. } List keys = new ArrayList(request.getParameterMap().keySet()); keys.remove(“sign”); // Exclude the sign parameter collections.sort (keys); / / sorting
StringBuilder sb = new StringBuilder(); for (String key : keys) { sb.append(key).append(“=”).append(request.getParameter(key)).append(“&”); LinkString = sb.toString(); linkString = sb.toString(); linkString = StringUtils.substring(linkString, 0, linkString.length() – 1); // Remove the last ‘&’
String secret = “Potato”; String sign = digestutils.md5HEX (linkString + secret); String sign = digestutils.md5hex (linkString + secret); // Mixed key MD5
return StringUtils.equals(sign, requestSign); } integrate MyBatis, Mapper plug-in, PageHelper plug-in, realize single table business zero SQL
-
Use the Druid Spring Boot Starter to integrate Druid database connection pool and monitoring
Use FastJsonHttpMessageConverter, raising the speed of the JSON serialization