Всем привет, я Лао Чжао!
1. Определение интерфейса
В работе необходимо определить различные интерфейсы, системную интеграцию для определения интерфейсов, внешние и внутренние вызовы для определения интерфейсов. Определение интерфейса может в определенной степени отражать навыки программирования программиста. Вот список проблем, которые я обнаружил на работе:
1. Формат возврата не является единым
Один и тот же интерфейс иногда возвращает массив, иногда возвращает один; в случае успеха он возвращает объект, а в случае неудачи возвращает строку сообщения об ошибке. На работе есть интерфейс системной интеграции, определенный таким образом, что очень раздражает. В этом соответствующем коде возвращаемый тип — map, json, object, чего быть не должно. В реальной работе мы определим унифицированный формат, которым является ResultBean, и есть еще один PageResultBean для пейджинга.
Пример ошибки:
//返回map可读性不好,尽量不要
@PostMapping("/delete")
public Map<String, Object> delete(long id, String lang) {
}
// 成功返回boolean,失败返回string,大忌
@PostMapping("/delete")
public Object delete(long id, String lang) {
try {
boolean result = configService.delete(id, local);
return result;
} catch (Exception e) {
log.error(e);
return e.toString();
}
}
2. Неумение считать неудачу
В начале рассматривались только успешные сценарии, а когда позже тесты выявили ошибки, что делать, менять интерфейс, менять и фронт и бэк офисы, что было бы бесполезно.
Пример ошибки:
//不返回任何数据,没有考虑失败场景,容易返工
@PostMapping("/update")
public void update(long id, xxx) {
}
3. Появляются входные параметры, не связанные с бизнесом
Например, на языке lang информация о текущем пользователе не должна отображаться в параметрах, а должна быть получена из текущей сессии. Позже ThreadLocal расскажет о том, как его удалить. Помимо проблемы плохой читаемости кода, особенно если параметр содержит информацию о текущем пользователе, это серьезная проблема.
Пример ошибки:
// (当前用户删除数据)参数出现lang和userid,尤其是userid,大忌
@PostMapping("/delete")
public Map<String, Object> delete(long id, String lang, String userId) {
}
4. Появляются сложные входные параметры
В общем, не допускаются такие параметры, как строки json, которые чрезвычайно удобочитаемы. Соответствующий компонент должен быть определен.
Пример ошибки:
// 参数出现json格式,可读性不好,代码也难看
@PostMapping("/update")
public Map<String, Object> update(long id, String jsonStr) {
}
5. Не возвращать данные, которые должны быть возвращены
Например, новый интерфейс обычно должен возвращать идентификатор нового объекта, что требует опыта программирования. Когда его определяет новичок, нецелесообразно не возвращать данные или возвращать только true, потому что передний план не используется. Хотят другие или нет - это чье-то дело, ты должен вернуться или должен вернуться.
Пример ошибки:
// 约定俗成,新建应该返回新对象的信息,只返回boolean容易导致返工
@PostMapping("/add")
public boolean add(xxx) {
//xxx
return configService.add();
}
Многие считают, что технология тоже очень проста, и в ней нет ничего особенного, однако, прежде чем внедрять этот кодовый фреймворк, вам нужен унифицированный формат ResultBean для вашего интерфейса, а aop сделать несложно. Некоторые люди неправильно поняли, что статья на прошлых выходных была не о технологиях, а о том, как работают привычки кодирования.Если вы все еще сосредоточены на технологиях, то я не могу вам помочь. Точно так же, если в моих более поздних постах о привычках и нормах вы все же сосредоточитесь на технике, то потеряете арбуз и наберете кунжут.Постов много или технического пункта нет.
Прикрепите ResultBean без какого-либо технического содержания:
@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() {
super();
}
public ResultBean(T data) {
super();
this.data = data;
}
public ResultBean(Throwable e) {
super();
this.msg = e.toString();
this.code = FAIL ;
}
}
Унифицированная спецификация интерфейса может помочь избежать множества бесполезных переделок и возможных проблем. Это может сделать код более читабельным и облегчить дополнительную работу по АОП и автоматическому тестированию. Все должны обратить внимание.
2. Спецификация контроллера
В приведенных выше двух абзацах кода первый — это исходная экология, а второй абзац — это код, который я наконец доставил после указания спецификации определения интерфейса и использования технологии АОП, от 15 строк до 1 строки, почувствуйте сами. Далее поговорим о том, как реализуется волнующий всех АОП.
Давайте сначала поговорим о спецификации контроллера.Основное содержание — это содержимое в определении интерфейса.Пока вы следуете спецификации внутри, контроллер не представляет большой проблемы.Помимо этого, есть и другие моменты:
1. Все функции возвращают единый формат ResultBean/PageResultBean.
См. мое определение интерфейса по причине. АОП не может быть воспроизведен без единого формата.
2. ResultBean/PageResultBean выделены для контроллера, и передавать их обратно нельзя!
3. Контроллер преобразует формат параметра и не позволяет передавать такие объекты, как json и map, сервисам, а также не позволяет сервисам возвращать json и map.
В целом! Кто писал код, знает, что формат map и json гибкий, но читабельность плохая, если ставить бизнес-данные, читать каждый раз будет сложно. Определение bean-компонента требует много работы, но код намного чище.
4. Как правило, объекты Request и Response не допускаются в параметрах.
В основном проблема с читабельностью. В целом.
5. Нет необходимости распечатывать журналы
Журналы будут печататься в АОП, и я предлагаю, чтобы большинство журналов печатались на уровне служб.
Большинство спецификаций заключаются не в том, чтобы делать больше элементов, меньше делать и легче реализовать.
Определение ResultBean с универсальным использованием ломбока.
@Data
public class ResultBean<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int NO_LOGIN = -1;
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() {
super();
}
public ResultBean(T data) {
super();
this.data = data;
}
public ResultBean(Throwable e) {
super();
this.msg = e.toString();
this.code = FAIL;
}
}
Код AOP в основном печатает журналы и перехватывает исключения. Исключения должны отличать известные исключения от неизвестных. Неизвестные исключения находятся в центре нашего внимания. Мы можем делать некоторые уведомления по электронной почте. Известные исключения могут быть дополнительно подразделены, которые могут отличаться. Исключение возвращает другой результат код:
/**
* 处理和包装异常
*/
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 未知的异常,应该格外注意,可以发送邮件通知等
result.setMsg(e.toString());
result.setCode(ResultBean.FAIL);
}
return result;
}
}
Конфигурация AOP: (Что касается использования кода Java или конфигурации xml, здесь я предпочитаю конфигурацию xml, потому что время от времени она будет меняться)
<!-- aop -->
<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>
Теперь я знаю, зачем возвращать унифицированный ResultBean: 1. Чтобы унифицировать формат, 2. Чтобы применить АОП, 3. Чтобы обернуть информацию об исключении.
PageResultBean подкачки аналогичен, каждый может заполнить его самостоятельно.
Вставьте простой контроллер (стрелка слева указывает на перехват АОП). Пожалуйста, сравните и просмотрите исходный код в худшем коде Java, который я когда-либо видел.Без сравнения нет вреда.
Наконец, существует унифицированная спецификация определения интерфейса, а затем реализована АОП. Сначала приходят идеи, а затем технологии. Технология не является ключом, и технология АОП также очень проста.Ключевой момент этого поста не технология, а привычки и идеи.Не собирайте семена кунжута и не теряйте арбуз. В интернете много постов, в которых говорится о технологиях, но меньше о привычках и стилях.Это эффективные опыты, над которыми я работала много лет.
Автор: Сяофэнцин
Ссылка: https://zhuanlan.zhihu.com/p/28708259
Замечательная рекомендация 1. 3 года опыта работы, не могу ответить ни на один из 5 способов связи между многопоточностями, вы можете в это поверить?
2. Плагин IDEA на уровне бога! В 50 раз эффективнее!
3. Запутался! С HTTP, почему RPC?
4. До свидания, Java-дженерики T, E, K, V, ?. На подходе универсальные дженерики, очень круто!
8. Нашел артефакт инструмента визуализации JSON, он мне так нравится!
9. Тяжелый! Tencent официально открыл исходный код Spring Cloud Tencent, догоняя Spring Cloud Alibaba!
10. Redis+Guava, взрыв производительности! Это сочетание действительно прекрасно....