[Springboot develop monomer web shop] 3. User Registration achieve

User Registration

As a modern business platform, what is most important? of course the users, the majority of users support groups are the cornerstone of our sustainable development 顾客是上帝, although in today God has not been taken seriously, especially a lot of the old platform for the user is anxious to hasten Out ... but is the foundation of all subscribers , then we start creating our God now!

## Creating a database

Part of the database, I'm not here to talk about, and we need, then you can go directly to the portal crawl script expensive-shop.sql.

# # Generation UserMapper

Section on Reference: Portal

## write business logic

First, let's analyze To register a user, the system we all need to do what action?
user register

  • validate
    • input string (we need to check-processed by two angles)
      • FrontEnd valid

        Front-end verification is to reduce our server side pressure to do part of the check, this part of the check can intercept most of the bad request.

      • Backend valid

        Back-end verification is to prevent some unscrupulous junior partner in order to bypass the front-end direct access to our server api error caused by data requests, or front-end program partners have a small bug ... no matter what kind of possibilities, are likely to cause serious s consequence.

    • email & mobile invalid

      Because I did not pursue email / SMS server, so this step will pass, small partners can own research Kazakhstan.

  • control
    • create user

      After checking through, you can create a user action.
      Next, we can achieve business since the actual coding, we use the most basic layered architecture, until we have passed Mybatis Generatorto generate the basic tools pojo, mapperfor simple operation we just need to write serviceand controllerlayers to complete our development work.

## write user service

In mscx-shop-servicecreating the com.liferunner.service.IUserServiceinterface contains two methods findUserByUserName, and createUser, as follows:

public interface IUserService {

    /**
     * 根据用户名查询用户是否存在
     *
     * @param username
     * @return
     */
    Users findUserByUserName(String username);

    /**
     * 创建用户
     *
     * @param userRequestDTO 用户请求dto
     * @return 当前用户
     */
    Users createUser(UserRequestDTO userRequestDTO) throws Exception;
}

Next, we need to implement this interface specific categories, as follows:

@Service
@Slf4j
public class UserServiceImpl implements IUserService {
    private final String FACE_IMG = "https://avatars1.githubusercontent.com/u/4083152?s=88&v=4";

    // 构造器注入
    private final UsersMapper usersMapper;
    private final Sid sid;

    @Autowired
    public UserServiceImpl(UsersMapper usersMapper, Sid sid) {
        this.usersMapper = usersMapper;
        this.sid = sid;
    }

    @Override
    public Users findUserByUserName(String username) {
        // 构建查询条件
        Example example = new Example(Users.class);
        val condition = example.createCriteria()
                .andEqualTo("username", username);
        return this.usersMapper.selectOneByExample(example);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Users createUser(UserRequestDTO userRequestDTO) throws Exception {
        log.info("======begin create user : {}=======", userRequestDTO);
        val user = Users.builder()
                .id(sid.next()) //生成分布式id
                .username(userRequestDTO.getUsername())
                .password(MD5GeneratorTools.getMD5Str(userRequestDTO.getPassword()))
                .birthday(DateUtils.parseDate("1970-01-01", "yyyy-MM-dd"))
                .nickname(userRequestDTO.getUsername())
                .face(this.FACE_IMG)
                .sex(SexEnum.secret.type)
                .createdTime(new Date())
                .updatedTime(new Date())
                .build();
        this.usersMapper.insertSelective(user);
        log.info("======end create user : {}=======", userRequestDTO);
        return user;
    }
}

There are several places it is necessary to explain:

UserServiceImpl # findUserByUserName Description

  • tk.mybatis.mapper.entity.ExampleConstructed by the use of query parameters mybatis Example, if there is a plurality of query conditions, can be example.createCriteria().addxxxadded one by one.

UserServiceImpl # createUser Description

  • @Transactional(propagation = Propagation.REQUIRED), Open transaction, select the transaction propagation level REQUIRED, represents a transaction must be present, if the caller transaction does not exist, then the method will open a new own thing, if the caller itself there is an active transaction, then this method will added into it (with the total death).
  • org.n3r.idworker.SidThis is an open source distributed ID generator component, portal , later given the chance, I will write a special article id generator.
  • MD5GeneratorToolsMD5 is used for data encryption tools, you can download the source code. You can also use direct java.security.MessageDigestdirect encryption to achieve, in short, password can not be stored in plain text on the line.
  • SexEnumThis is a type of enumeration gender representation in our encoding specifications, requirements as much as possible not to appear Magic number, the development community is often said that the magic number (ie, 1,2,300 ...)
  • Here's print journal, one might ask why you did not notice like this: private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);, it is because we are in the beginning, we have introduced lombokdependence not remember the students can refer to the portal . Here dependence, it inherited a lot of logging component, we only need to use an annotation lombok.extern.slf4j.Slf4jto open the log, use log.info..it.
  • UserRequestDTOWhat is a ghost? In the process of our development, is likely to be high-volume parameters need to be passed, then if we use xxx#(String aa,Integer bb,Boolean cc...)makes us the number of very annoying, but do not look beautiful, this time we can choose to create a new object to help us transfer data, so that is our UserRequestDTOtarget, so-called DTOis Data Transfer Objectan acronym, as the name implies, it is used to transfer data objects used.

## write user controller

Also in mscx-shop-api, create com.liferunner.api.controller.UserController, implement user-created.

@RestController
@RequestMapping(name = "/users")
@Slf4j
@Api(tags="用户管理")
public class UserController {

    @Autowired
    private IUserService userService;

    @ApiOperation("校验是否重名")
    @GetMapping("/validateUsername")
    public JsonResponse validateUsername(@RequestParam String username) {
        // 判断用户名是否非法
        if (StringUtils.isBlank(username))
            return JsonResponse.errorMsg("用户名不能为空!");
        if (null != userService.findUserByUserName(username))
            return JsonResponse.errorMsg("用户名已存在!");
        // 用户名可用
        return JsonResponse.ok();
    }

    @ApiOperation("创建用户")
    @PostMapping("/create")
    public JsonResponse createUser(@RequestBody UserRequestDTO userRequestDTO) {
        try {
            if (StringUtils.isBlank(userRequestDTO.getUsername()))
                return JsonResponse.errorMsg("用户名不能为空");
            if (null != this.userService.findUserByUserName(userRequestDTO.getUsername())) {
                return JsonResponse.errorMsg("用户名已存在!");
            }
            if (StringUtils.isBlank(userRequestDTO.getPassword()) ||
                    StringUtils.isBlank(userRequestDTO.getConfimPassword()) ||
                    userRequestDTO.getPassword().length() < 8) {
                return JsonResponse.errorMsg("密码为空或长度小于8位");
            }
            if (!userRequestDTO.getPassword().equals(userRequestDTO.getConfimPassword()))
                return JsonResponse.errorMsg("两次密码不一致!");
            val user = this.userService.createUser(userRequestDTO);
            if (null != user)
                return JsonResponse.ok(user);
        } catch (Exception e) {
            log.error("创建用户失败,{}", userRequestDTO);
        }
        return JsonResponse.errorMsg("创建用户失败");
    }
}

UserController#validateUsername(username) 说明

  • JsonResponseThe object is returned to the client in order to facilitate a uniform format encapsulated data objects.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonResponse {

    // 定义jackson对象
    private static final ObjectMapper MAPPER = new ObjectMapper();
    // 响应业务状态
    private Integer status;
    // 响应消息
    private String message;
    // 响应中的数据
    private Object data;

    public static JsonResponse build(Integer status, String msg, Object data) {
        return new JsonResponse(status, msg, data);
    }

    public static JsonResponse ok(Object data) {
        return new JsonResponse(data);
    }

    public static JsonResponse ok() {
        return new JsonResponse(null);
    }

    public static JsonResponse errorMsg(String msg) {
        return new JsonResponse(500, msg, null);
    }

    public static JsonResponse errorMap(Object data) {
        return new JsonResponse(501, "error", data);
    }

    public static JsonResponse errorTokenMsg(String msg) {
        return new JsonResponse(502, msg, null);
    }

    public static JsonResponse errorException(String msg) {
        return new JsonResponse(555, msg, null);
    }

    public static JsonResponse errorUserQQ(String msg) {
        return new JsonResponse(556, msg, null);
    }

    public JsonResponse(Object data) {
        this.status = 200;
        this.message = "OK";
        this.data = data;
    }

    public Boolean isOK() {
        return this.status == 200;
    }
}

UserController#createUser(UserRequestDTO) 说明

  • As is stated above, a variety of verification need to do first
  • Success, returnsJsonResponse
  • Observant students may have seen above there are a few notes @Api(tags="用户管理"), @ApiOperation("创建用户")this is Swagger's comments, and we'll discuss in the next section to find out more, and how to generate off-line docs.

Test API


After we each modification completed, as far as possible the mvn clean installtime, because we belong to different of the project, if you do not reinstall, occasional problems may cast doubt on life.

...
[INFO] expensive-shop ..................................... SUCCESS [  1.220 s]
[INFO] mscx-shop-common ................................... SUCCESS [  9.440 s]
[INFO] mscx-shop-pojo ..................................... SUCCESS [  2.020 s]
[INFO] mscx-shop-mapper ................................... SUCCESS [  1.564 s]
[INFO] mscx-shop-service .................................. SUCCESS [  1.366 s]
[INFO] mscx-shop-api ...................................... SUCCESS [  4.614 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  20.739 s
[INFO] Finished at: 2019-11-06T14:53:55+08:00
[INFO] ------------------------------------------------------------------------

When you see the results of the above operation, you can start testing our application on-line friends ~

UserController#validateUsername(username) 测试

There are many ways to test the API, for example curl localhost:8080/validateUsername, in such super popular Postmanis completely ok, I am here is before the first chapter of a plug-and everyone said Restful Toolkit(可以实现和postman一样的简单效果,同时还能帮助我们生成一部分测试信息), when we start the application, the following picture,
rest plugin

We can see that the plug-in to help us generate several test methods, such as we click validateUsername, it will generate the current method is below contains a usernameparameter GETmethod demoDatais the default plug-in to our test data generated. It can be freely modified.
Click Send:
result
you can see the request is successful, and returns JSON data format our custom.

UserController#createUser(UserRequestDTO) 测试

Then we continue to test the user registration interface to request the following:
send
you can see, when we choose createthe time method, plug-in automatically help us set the request type POST, and RequestBodydefault values also helped us to create, I only modified the default usernameand passwordthe value confimPasswordof I did not change the default value, that according to our validation logic, it should be returned return JsonResponse.errorMsg("两次密码不一致!");to this line, click Send:
result
modifications confimPasswordto 12345678, click Send:
result2
you can see, create user success, and will return the user to create our current customers request end. So we continue to create repeated clicks, what will happen? Continue Send:
result3
you can see, our users have also become effective verification repeat it.

Notice under section


The next section we will learn how to use Swagger API interface to automatically generate documentation to the next front-end, as well as the situation if there is no external network, or when you need a third-party platform and docking, how we generate 离线文档to the third party.
gogogo!

Guess you like

Origin www.cnblogs.com/zhangpan1244/p/11809826.html