SpringBoot разумно использует интерфейсы для разделения бизнес-кода и логического кода.

Spring Boot
SpringBoot разумно использует интерфейсы для разделения бизнес-кода и логического кода.

Нет предела метанию, технологии бесконечны

предисловие

Когда не будет стандартизации разработки 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;
}

Пока проблема того, как внедрить класс реализации интерфейса в уровень контроллера, полностью решена.

Написано в последнюю

  • Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь 😊
  • Эта статья была впервые опубликована в Наггетс, если вам нужно перепечатать, пожалуйста, оставьте сообщение в области комментариев 💌
Категории