Why Unified API Responses Matter: Mastering Spring Boot Controllers and AOP
This article explains common pitfalls in Java API design—such as inconsistent return formats, missing error handling, and inappropriate parameters—and demonstrates how a unified ResultBean, strict controller conventions, and AOP logging can dramatically improve code readability, maintainability, and error management in Spring Boot projects.
1. Interface Definition
In daily development we must define various APIs; the way an interface is defined reflects a programmer's skill. Common problems include:
Inconsistent return formats (sometimes an array, sometimes a single object; success returns an object, failure returns a string).
Ignoring failure scenarios, leading to refactoring when errors appear.
Including unrelated parameters such as language or user ID that should be obtained from the session.
Using complex input types like raw JSON strings instead of proper beans.
Not returning required data (e.g., a newly created object's ID).
Incorrect examples
// returning map is hard to read, avoid it
@PostMapping("/delete")
public Map<String,Object> delete(long id, String lang) {
// ...
return result;
}
// success returns boolean, failure returns string – bad practice
@PostMapping("/delete")
public Object delete(long id, String lang) {
try {
boolean result = configService.delete(id, lang);
return result;
} catch (Exception e) {
log.error(e);
return e.toString();
}
}
// no data returned, failure scenario ignored
@PostMapping("/update")
public void update(long id, Xxx xxx) {
// ...
}
// passing JSON string as parameter – unreadable
@PostMapping("/update")
public Map<String,Object> update(long id, String jsonStr) {
// ...
}2. Controller Standards
All controller methods should return a unified ResultBean (or PageResultBean) so that AOP can operate uniformly.
Only the controller should convert request parameters; services must not receive raw Map or JSON objects.
Avoid exposing HttpServletRequest or HttpServletResponse in service layer.
Do not log inside controllers; logging is handled by AOP, while business‑level logs belong in services.
ResultBean definition (using Lombok)
@Data
public class ResultBean<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int SUCCESS = 0;
public static final int FAIL = 1;
public static final int NO_PERMISSION = 2;
private String msg = "success";
private int code = SUCCESS;
private T data;
public ResultBean() {}
public ResultBean(T data) { this.data = data; }
public ResultBean(Throwable e) {
this.msg = e.toString();
this.code = FAIL;
}
}3. AOP for Controllers
The AOP aspect wraps controller execution, logs execution time, and converts any thrown exception into a ResultBean with appropriate error codes.
public class ControllerAOP {
private static final Logger logger = LoggerFactory.getLogger(ControllerAOP.class);
public Object handlerControllerMethod(ProceedingJoinPoint pjp) {
long startTime = System.currentTimeMillis();
ResultBean<?> result;
try {
result = (ResultBean<?>) pjp.proceed();
logger.info(pjp.getSignature() + " use time:" + (System.currentTimeMillis() - startTime));
} catch (Throwable e) {
result = handlerException(pjp, e);
}
return result;
}
private ResultBean<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
ResultBean<?> result = new ResultBean();
if (e instanceof CheckException) {
result.setMsg(e.getLocalizedMessage());
result.setCode(ResultBean.FAIL);
} else if (e instanceof UnloginException) {
result.setMsg("Unlogin");
result.setCode(ResultBean.NO_LOGIN);
} else {
logger.error(pjp.getSignature() + " error", e);
// TODO: notify unknown exceptions (e.g., email)
result.setMsg(e.toString());
result.setCode(ResultBean.FAIL);
}
return result;
}
}AOP configuration (XML)
<aop:aspectj-autoproxy/>
<beans:bean id="controllerAop" class="xxx.common.aop.ControllerAOP"/>
<aop:config>
<aop:aspect id="myAop" ref="controllerAop">
<aop:pointcut id="target" expression="execution(public xxx.common.beans.ResultBean *(..))"/>
<aop:around method="handlerControllerMethod" pointcut-ref="target"/>
</aop:aspect>
</aop:config>4. Visual Example
The following diagram shows a simple controller before and after applying the unified ResultBean and AOP interception.
In summary, a unified response format enables consistent AOP handling, reduces repetitive refactoring, improves readability, and facilitates automated testing and error monitoring.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
