Нет предела метанию, технологии бесконечны
предисловие
Когда не будет стандартизации разработки Java, код бизнес-логики и утилиты будут разделены, если возникнут изменения спроса, потребуется время, чтобы изменить общедоступную логику, нужно найти бизнес-код везде, большая трата времени, после интерфейса разумно решить эту проблему.
концепция интерфейса
- Класс объявлен с использованием интерфейса
- Только идентификатор метода, без тела метода
- Интерфейсы похожи на чертежи, указывающие, что класс должен и чего не может делать.
- Все методы в интерфейсе являются абстрактными и общедоступными, а все свойства являются общедоступными, статическими и конечными.
- Если класс хочет реализовать интерфейс, он должен реализовать все методы интерфейса.
Роль интерфейса
- Многократное наследование: поскольку Java не совпадает с C ++, поддерживает множественное наследование, Java может составить эту проблему, реализуя интерфейс.
- Интерфейс может быть развязан
- Логический код можно отделить от бизнес-кода
синтаксис интерфейса
- Объявить класс с интерфейсом и объявить метод регистрации внутри класса
public interface UserService {
// 声明一个方法
public void method();
}
- Создайте класс реализации интерфейса и используйте Override для переопределения методов, объявленных в интерфейсе.
// 实现接口中声明的方法
@Override
public void method() {
// +++++++ 具体的实现 +++++++
}
На этом объявление интерфейса завершено.
практическое применение
Давайте сначала посмотрим на реализацию функций и бизнес-кода, когда интерфейс не используется.controllerКод уровня, здесь мы берем логин в качестве примера. Если мы сталкиваемся с новыми требованиями, нам нужно найти часть реализации функции, которую нужно изменить. Это головная боль, когда слишком много бизнес-кодов.
@RestController
@RequestMapping("/user")
public class GreetingController {
private final Logger logger= LoggerFactory.getLogger(getClass());
@Resource
private UserInfoMapper userMapper;
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@CrossOrigin()
// 登录请求
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@RequestBody String request){
// 获取前端参数
JSONObject jsReq = new JSONObject(request);
JSONObject jsReply = new JSONObject();
String username = jsReq.getString("username");
String password = jsReq.getString("password");
UserInfo row = new UserInfo();
JSONArray queryType = new JSONArray();
queryType.put("name");
queryType.put("password");
queryType.put("career");
queryType.put("avatarSrc");
queryType.put("userID");
row.setQueryType(queryType);
row.setName(username);
List<UserInfo> resultList = userMapper.customQuery(row);
JSONArray result = null;
if(resultList.size()>0){
result = new JSONArray(resultList);
if(password.equals(result.getJSONObject(0).getString("password"))){
jsReply.put("code",0);
// 根据当前用户名和密码生成token
jsReply.put("token", JwtUtil.sign(username,password));
jsReply.put("msg","验证成功,token有效期为30分钟");
jsReply.put("avatarSrc",result.getJSONObject(0).getString("avatarSrc"));
jsReply.put("userID",result.getJSONObject(0).getString("userID"));
}else{
jsReply.put("code",-2);
jsReply.put("msg","密码错误");
}
}else{
jsReply.put("code",-1);
jsReply.put("msg","当前登录用户不存在");
}
return jsReply.toString();
}
}
- Используйте интерфейс для разделения кода вышеприведенных сценариев (здесь мы берем функцию регистрации в качестве примера)
// service层
package com.lk.service;
import com.lk.enums.ResultEnum;
public interface UserService {
// 新用户注册接口
public ResultEnum AddUser(String userName, String password, String avatarSrc) throws Exception;
}
// serviceimpl层(接口实现)
package com.lk.serviceimpl;
import com.lk.dao.UserMapper;
import com.lk.entity.User;
import com.lk.enums.ResultEnum;
import com.lk.service.UserService;
import com.lk.utils.DateUtil;
import com.lk.utils.HMacMD5;
import com.lk.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
// @Slf4j是lombok的注解,使用此注解后可以在当前类直接使用log关键字来打印日志
@Slf4j
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
// 从配置文件读取加密key
@Value("${HMacKey}")
private String HMacKey;
// 实现注册接口
@Override
public ResultEnum AddUser(String userName, String password, String avatarSrc) throws Exception {
// 判断参数是否合法
if(StringUtils.isBlank(userName) ||userName.length()>10){
log.error("违规操作:用户名为空或用户名长度大于10,"+userName);
return ResultEnum.USER_ERROR;
}
if(StringUtils.isBlank(password)||password.length()>16){
log.error("违规操作:密码为空或密码长度大于10,"+password);
return ResultEnum.PASSWORD_ERR;
}
if(StringUtils.isBlank(avatarSrc)||avatarSrc.length()>300){
log.error("违规操作:头像地址为空或头像地址过长,"+avatarSrc);
return ResultEnum.AVATAR_ERR;
}
// 对密码进行加密
password = HMacMD5.encryptHMAC2String(password,HMacKey);
User row = new User();
row.setUserName(userName);
row.setUserId(UUIDUtil.getUUID());
row.setPassword(password);
row.setAvatarSrc(avatarSrc);
row.setCreateTime(DateUtil.getThisTime());
log.info(userMapper+"");
// 增加用户,向数据库插入一条数据
int result = userMapper.insertUser(row);
return ResultEnum.SUCCESS;
}
}
// controller层(业务代码)
package com.lk.controller;
import com.lk.VO.ResultVO;
import com.lk.dao.UserMapper;
import com.lk.entity.User;
import com.lk.enums.ResultEnum;
import com.lk.serviceimpl.UserServiceImpl;
import com.lk.utils.ResultVOUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(value = "/api/user", tags = "用户信息接口模块")
@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {
// 注入用户接口
@Resource(name = "userServiceImpl")
private UserService userService;
@ApiOperation(value = "注册接口", notes = "传用户名、密码、头像地址来注册用户")
@RequestMapping(value = "/registered", method = RequestMethod.POST)
public ResultVO registered(@RequestBody User user) throws Exception {
// 调用注册接口
ResultEnum result = userService.AddUser(user.getUserName(),user.getPassword(),user.getAvatarSrc());
// 获取返回枚举的code判断是否成功
if(result.getCode()==0){
return ResultVOUtil.success(result.getMessage());
}
return ResultVOUtil.error(result.getCode(),result.getMessage());
}
}
Особая благодарность
Спасибо разработчикам в комментариях за их предложения, которые дали мне понять, что у меня много Java.До написания проектов я разрабатывал свободно.Многие сценарии не учитывались, и код, который я писал, был грязным. На самом деле я не участвовал в разработке Java-проекта компании, потому что я штатный фронтенд, и я надеюсь, что все будут терпеть меня за неуместные места в тексте. В ответ на предложения разработчиков в области комментариев я внес следующие изменения:
- Контроллер не должен писать никакой логики, а только управлять, а весь код логики помещать в реализацию интерфейса.
- Декларация класса Enum Использование набора именованных констант, связанных с интерфейсом, легко определить, является ли операция успешной, магический номер для решения проблемы
- Измените тип возвращаемого интерфейса на перечисление
- Измените предыдущий json, чтобы получить метод внешнего интерфейса, используяdtoполучить параметры интерфейса
- Перед изменением метода возврата возвращаемых данных с использованием структуры json используйтеVOПредставление результатов возвращает параметры во внешний интерфейс.
- Интегрированный swagger, используемый для создания документации интерфейса
- Что касается комментариев, раздел @Muruxing Developers говорят, почему я не использую идею аннотаций @autovired, потому что при использовании этой аннотации будут предупреждение о желтых линиях, поэтому я использовал @Resource, но я принимаю во внимание тот же интерфейс, может иметь много реализации Класс, я использую класс реализации к каждому инъекции @service («userserviceImpl»), то @Resource (name = "usererviceImpl") метод инстанции Соответствующие классы внедрения, используемые в контроллере
- Используйте аннотацию @Slf4j, чтобы исключить фабричный объект, который создает экземпляр регистратора перед
Побить пит-рекорд
Когда уровень контроллера использует интерфейс для реализации метода в классе, содержимое аннотации spring всегда равно null, а объект сопоставления в mybatis аннотируется @Resource, а атрибуты в файле yml не могут быть получены с помощью аннотации @Value. , а класс реализации интерфейса сообщает об аномальном нулевом указателе. Причина в том, что когда я создаю экземпляр класса реализации интерфейса на уровне контроллера, объект сам по себе новый, и я не заходил в Spring, поэтому он всегда равен нулю. Я нашел много решений и много обходных путей и, наконец, использовал аннотацию @Service и аннотацию @Resource, чтобы идеально решить эту проблему. Мою проблему можно описать так: как внедрить класс реализации интерфейса на уровне контроллера.
- Реализуйте объект класса в собственном новом интерфейсе уровня контроллера.
// 错误的解决方案,实现类不走spring容器,报空指针异常
UserServiceImpl userService = new UserServiceImpl();
- Используйте аннотацию @service в классе реализации интерфейса и используйте инъекцию @Resource на уровне контроллера.
// 这里括号中的名字为当前类名首字母小写
@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
/////++++++++++++++++++++++++/////
}
// controller层
public class UserController {
// 括号里的name值对应接口实现类@Service注解括号里的名字
@Resource(name = "userServiceImpl")
private UserService userService;
}
Пока проблема того, как внедрить класс реализации интерфейса в уровень контроллера, полностью решена.
Написано в последнюю
- Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь 😊
- Эта статья была впервые опубликована в Наггетс, если вам нужно перепечатать, пожалуйста, оставьте сообщение в области комментариев 💌