1. Parameter management
In programming system, in order to write good code, is based on a variety of design patterns, principles, constraints, to standardize the code, such as to improve the readability of the code, reusability, can modify, actually think, if you write the code is very good, that is the thinking of others change also can’t destroy the original author and encapsulation, this should be a very high level.
However, in daily development, due to many objective factors, there is little time to constantly think and optimize the code, so I can only think about how to build the system code from the perspective of the actual situation, to ensure that I can read my own code in the future. In my years of programming, I will actually consider the following aspects: Code level management, unified naming and annotation, reasonable design of business database, clear parameter style.
Here to talk about parameter management, around: entry, verification, return three aspects of the content.
How to understand the concept of code specification: The constraints that most developers agree on and are willing to follow, such as the Spring framework and Mvc pattern for project management, and the Java Development Manual for business development, are all fundamentally aimed at preventing code from becoming unmaintainable as the business grows.
2. Receiving parameters
There are many ways to receive parameters, such as List, Map, Object, etc., but in order to clarify the semantics of parameters, it is usually necessary to design the structure of parameter objects and comply with certain specifications, for example, explicitly forbid Map to receive parameters:
The Rest style accepts a single ID parameter:
@GetMapping("/param/single/{id}")
public String paramSingle (@PathVariable Integer id){
return "Resp:"+id ;
}
Copy the code
Accepts more than one specified argument:
@GetMapping("/param/multi")
public String paramMulti (@RequestParam("key") String key, @RequestParam("var") String var){
return "Resp:"+key+var ;
}
Copy the code
Java-based wrapper object entry:
@PostMapping("/param/wrap")
public ParamIn paramWrap (@RequestBody ParamIn paramIn){
returnparamIn ; } -- Parameter object entitypublic class ParamIn {
private Integer id ;
private String key ;
private String var ;
private String name ;
}
Copy the code
The above are common methods of adding parameters in development. The following conventions are generally followed:
- Parameter semantics: specify the role of receiving parameters;
- Limit number of arguments: more than three use wrapper objects;
- Avoid multiple interfaces using a single wrapper object entry.
- Avoid wrapping the object body too complex;
Parameter receives no complicated constraints, on the whole is more easy to follow, often the problem is that when handling large subject object, easy to produce more than a wrapper object is reuse, leading to object field properties are many, is particularly vulnerable to this kind of situation in complex business and the object is not conducive to the web interface to use, Or most of the time, objects are mixed between the business layer and the interface layer;
Encapsulate complex BO objects at the business layer to reduce the complexity of service management. This is a reasonable and common operation. You can manage the input subjects at the Web interface level according to the interface functions, and then pass them into the BO objects during service implementation.
Avoid complex business wrapper objects floating around the layers, which can easily confuse developers if multiple interface input parameters are the same complex object.
3. Response parameters
Corresponding to the parameter reception is the parameter response, which usually has a clear constraint specification: response subject data, response code, description information. Generally speaking, these are the three core elements.
Response parameter body:
The use of generics here is usually used for receiving body data.
public class Resp<T> {
private int code ;
private String msg ;
private T data ;
public static <T> Resp<T> ok (T data) {
Resp<T> result = new Resp<>(HttpStatus.OK);
result.setData(data);
return result ;
}
public Resp (HttpStatus httpStatus) {
this.code = httpStatus.value();
this.msg = httpStatus.getReasonPhrase();
}
public Resp(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data; }}Copy the code
Code status Code
It is recommended to refer to and follow the description of the status code in HttpStatus, which is generally followed by development specifications. If the business requirements are not met, you can fully customize a set of response codes in the appropriate custom part of the code, but there is not much need.
Msg to describe
Msg that describes the response of the interface may be: success or failure. More often, it is necessary to deal with the prompt message of the service exception, such as the single number does not exist, the account is frozen, etc. Usually, it is necessary to capture the prompt message from the service exception and respond to the page, or the description of the failed input parameter verification.
The Data of Data
The main data of the interface response, the object of different business response must be different, so here based on the generic mechanism can receive, and then respond to the page in JSON format.
Refer to the case
Interface return parameter:
@PostMapping("/resp/wrap")
public Resp<KeyValue> respWrap (@RequestBody KeyValue keyValue){
return Resp.ok(keyValue) ;
}
Copy the code
Response format:
{
"code": 200."msg": "OK"."data": {
"key": "hello"."value": "world"}}Copy the code
4. Parameter verification
Parameter reception and response are relatively not complex, but the parameter verification is more difficult to deal with: input constraint verification, service validity verification, non-null and non-null verification of response parameters, and other scenarios.
In the process of system operation, no parameter is absolutely reliable, so parameter verification can be seen everywhere. Parameter verification in different scenarios has its necessity, but its fundamental purpose is to prompt information to the requestor, interrupt the process quickly, and respond quickly.
1. Reference
Many of the encapsulation ideas, design patterns, or parameter validation here, can be referred to existing Java source code or excellent frameworks, which is a basic awareness to have.
Java native method java.lang.Thread Thread:
public void interrupt(a) {
if (this! = Thread.currentThread()) checkAccess();synchronized (blockerLock) {
Interruptible b = blocker;
if(b ! =null) {
interrupt0();
b.interrupt(this);
return;
}
}
interrupt0();
}
Copy the code
In Java source code, most of them are using the native if judgment method to perform verification of parameters
The Spring framework of org. Springframework. Util. ClassUtils tools part of the code:
public staticClass<? > forName(String name,@Nullable ClassLoader classLoader)
throws ClassNotFoundException, LinkageError {
Assert.notNull(name, "Name must not be null"); Class<? > clazz = resolvePrimitiveClassName(name);if (clazz == null) {
clazz = commonClassCache.get(name);
}
if(clazz ! =null) {
returnclazz; }}Copy the code
In the Spring framework in addition to the base if judgment, also encapsulate a org. Springframework. Util. Assert tools.
2. Common verification methods
If judgment
@GetMapping("/check/base")
public String baseCheck (@RequestParam("var") String var){
if (var= =null) {
return var+" is null" ;
}
if ("".equals(var)) {return var+" is empty" ;
}
if ("hello".equals(var)) {return var+" sensitive word " ;
}
return var + " through " ;
}
Copy the code
This kind of judgment is common in code, but it is error-prone on one side and patient on the other if you have to write if judgments repeatedly in a distributed environment when the subject object is large for validation.
Valid component
In the early years, the popular Validator component, hibernate-Validator, and the later validation-API, were said to reference the former implementation, but that doesn’t matter; both simplify the Validation mechanism for Javabeans.
Annotated, marks the field properties of a Java object and sets a warning if validation fails.
public class JavaValid {
@notnull (message="ID cannot be empty ")
private Integer id ;
@email (message=" Email format is abnormal ")
private String email ;
@notempty (message = "field cannot be empty ")
@size (min = 2, Max = 10,message = "error ")
private String data ;
}
Copy the code
Verification result print:
public class JavaValidTest {
private static Validator validator ;
@BeforeClass
public static void beforeBuild (a){
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
@Test
public void checkValid (a){
JavaValid valid = new JavaValid(null."email"."data"); Set<ConstraintViolation<JavaValid>> validateInfo = validator.validate(valid) ;// Prints the verification result
validateInfo.stream().forEach(validObj -> {
System.out.println("validateInfo:"+validObj.getMessage()); }); }}Copy the code
Interface use:
@PostMapping("/java/valid")
public JavaValid javaValid (@RequestBody @Valid JavaValid javaValid,BindingResult errorMsg){
if (errorMsg.hasErrors()){
List<ObjectError> objectErrors = errorMsg.getAllErrors() ;
objectErrors.stream().forEach(objectError -> {
logger.info("CheckRes:{}",objectError.getDefaultMessage());
});
}
return javaValid ;
}
Copy the code
This verification mechanism is based on annotations and can greatly simplify common input verification. However, it is not suitable for legitimate verification of service parameters, such as common ID nonexistent and state interception.
Assert
The Assert Assert approach was common in unit testing and later in various good frameworks such as Spring, Mybatis, and then in business code:
public class AssertTest {
private String varObject ;
@Before
public void before (a){
varObject = RandomUtil.randomString(6); }@Test
public void testEquals (a){
Assert.assertEquals(varObject+"No match",varObject,RandomUtil.randomString(6));
}
@Test
public void testEmpty (a){
Assert.assertTrue(StrUtil.isNotEmpty(varObject));
Assert.assertFalse(varObject+" not empty",StrUtil.isNotEmpty(varObject));
}
@Test
public void testArray (a){
/* Arrays first differed at element [1]; Expected :u08 Actual :mwm */
String var = RandomUtil.randomString(5); String[] arrOne =new String[]{var,RandomUtil.randomString(3)}; String[] arrTwo =new String[]{var,RandomUtil.randomString(3)}; Assert.assertArrayEquals(Array elements are not equal,arrOne,arrTwo); }}Copy the code
Assert assertions are a popular alternative to traditional if judgments, greatly reducing the number of lines of code required for parameter verification and improving program readability.
Five, source code address
Making address GitEE, https://github.com/cicadasmile/middle-ware-parent, https://gitee.com/cicadasmile/middle-ware-parentCopy the code