Use springboot create a Shopping Mall

First of all, congratulations own (pseudo) independently completed a background including management and front-end mall (extremely simple) mall system.
In this process, my main question is - uh, nothing will!
Yes, really nothing will. A month ago, the only basis for this project help I have is: self-study using eclipse two weeks for java programming algorithm. In addition, there is no web project experience, there is no spring experience, no experience in J2EE. At school I had only learned c ++, and is limited to the algorithm.
Honestly, when I faced this project proposition, I feel a deep despair and regret for past neglect of time. So, I started to do the first thing, log b station, click to open the highest spring, springmvc, mybatis, springboot video. . . . .
Keke, gossip digress, back to the topic!
This blog I will show as completely as possible to build logical thinking and business system of a springboot mall. Of course, there are still some projects is not enough friendly bug, and functional thin disadvantages (I too lazy changed). Blog publishing, the main purpose of my thinking and knowledge of the past month consolidated summary, I will not enumerate all of the project content (such as additions and deletions to the object to change search operations, etc.), especially when I feel very simple part of it may seem comprehensive enough, if you need a comprehensive code, you can go on a search git front of the original code.
So the question is, can you rely on this blog successful completion of a project?
The answer is clearly no. Because I just summarize the focus of some personal experience in the project, I myself also learn the entire project completed by the video, blog, git other ways gradually. In other words, this is not a blog teaching class.
If you want to accomplish its own project, you need to see more video, more learning the basics, look for more blog, this is just a reference and you may not be able to reference. Only.
Basically, I would take the form of day (???) update, the gradual completion.

Technology stack

Because beginners, so the project is to use the most basic technical framework. as follows:

(Too lazy to hand to knock, direct ppt screenshot)
which springboot components are in parentheses after I complete the basic functions, adding supplementary by degree of your mother.

demand analysis

This is the beginning of the project began, the first work to be done. Of course, I would not do this step, until the project is almost, I was finishing a good needs analysis, it can be said to be very professional.

User needs analysis Reception

User Center:
1注册与登录
2用户个人信息(包括地址和积分信息)的查看与修改
3用户购物车的查看与修改
4个人订单的查看、取消、下单
5积分兑换商品记录查询
Shopping Mall:
1商品展示
2商品分类及展示
3商品详情
4商品加入购物车以及下单    
Order system:
1商品下单
2支付订单以及退单
Points Mall:
1积分商城
2积分获取规则
3积分兑换商品

Background administrator needs analysis

Admin Login

User Management:

1用户信息搜索查询
2用户信息增删改
3地址信息搜索查询
4用户地址信息增删改

Commodity Management:

1商城商品增删改查
2积分商品增删改查
3商品类别增删改查

Order Management:

1订单的分类查询
2订单的删改查

Integral Management:

1用户积分查询与修改
2积分兑换记录查询

mind Mapping

You can see, the mind map is organized into the following requirements analysis visualization graphical structure, making the entire project functions at a glance, but also can use the tags to record their completion, very comfortable. Likewise, of course, I do this step is not very good, at the beginning of the function list is not detailed enough, the idea is not clear, you can see, my function is quite thin (so that the dish is original sin ah!). So, mind mapping list, must be specific and detailed, each complete a do a mark, full of a sense of accomplishment!

Project combat (start line and the code)

This large module, I will use their own time to complete the project of writing steps. Basically, that is the back-end management platform - front-end management platform - the back-end mall - order store front end. Among them, the front part I spent more than three-fifths of the time, it takes less time for the back-end (front end is not really ah !!!). Because a lot of content is simple multiplexing (such as the background for the user, merchandise management operations), so I will not enumerate all.

Here, the first list what data sheets and project structure. Other details that later show.

Database Table

Project structure

Profile application.yml

spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
username: ######
password: ######
url: jdbc:mysql://localhost:3306/miaosha?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver

Jackson Configuration

jackson:
default-property-inclusion: NON_NULL
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
mvc:
view:
suffix: .html
prefix: /
#resources:
#classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
#static-locations: classpath:/css/, classpath:/image/, classpath:/js/
#static-path-pattern: /static/*

thymeleaf:
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
cache: false
#配置驼峰映射
configuration:
map-underscore-to-camel-case: true

mybatis Configuration

the mybatis:
typeAliasesPackage: com.pf.businessdemo.dataobject
mapperLocations: the CLASSPATH: Mapping / * xml.
the Configuration:
the Map-Underscore-to-CAMEL-Case: to true
(this is one of the most simple configuration, learned a little foundation must know everything .)
dependent other than injection and I no longer listed, it is a web jar package required for the project.

Background user module

First, log in registration

Users entity class

public class UserDo {
private Integer id;

private String name;

private String gender;

private Integer age;

private String telphone;

private String registerMode;

private String thirdPartyId;

private String receiverAddress;

private Integer integral;

getset omitted

service layer interface

interface UserService {public
/ **
@Description: acquire user information ID
@Param: ID
@return: User Domain Model usermodel
/
UserModel getUserById (ID Integer);

/**
*@Description:通过id删除用户信息
*@Param: id
*@return: void
*/
void deleteUser(Integer id);

/**
*@Description:通过name删除用户
*@Param:userdo
*@return:
*/
int  deleteByName(UserDo userDo );

/**
*@Description:通过id更改用户信息
*@Param: 要更改的用户信息
*@return: void
*/
void updateUserInfo(UserDo userDo);

/**
*@Description:完善用户信息
*@Param:用户填写的具体信息
*@return:
*/
UserDo insertUserInfo(UserDo userDo);

/**
*@Description:查询获取所有用户信息
*@Param:
*@return:list<userdo>
*/
List<UserDo> findUserAll();

/**
*@Description:联合查询用户及密码信息
*@Param:
*@return:
*/
List<UserPassWordDo> findDouble();

/**
*@Description:通过名字搜索用户
*@Param:用户信息
*@return:
*/
List<UserDo> findUserByName(UserDo userDo);

/**
*@Description: 用户注册接口
*@Param: 用户领域模型
*@return:
*/
void register(UserModel userModel)throws  BusinessException;

/**
*@Description:用户带校验的登陆接口
*@Param: 用户手机,用户加密密码
*@return:
*/
UserModel validateLogin(String telphone,String encrptPassword) throws BusinessException;

Here are all the service user interface currently only need to focus on the relevant log in to register.

UserServiceImpl

@Override
public List findUserByName(UserDo userDo) {
return userDoMapper.findUserByName(userDo);
}

@Override
@Transactional
public void register(UserModel userModel) throws BusinessException {
    if (userModel==null){
        throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
    }
    ValidationResult result=validator.validate(userModel);
    if (result.isHasError()){
        throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,result.getErrMsg());
    }
    //实现model->dataobject方法
    UserDo userDo=convertFromDataObject(userModel);
    try {
        userDoMapper.insertSelective(userDo);
    }catch (DuplicateKeyException ex){
        throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"手机号已重复注册");
    }
    userModel.setId(userDo.getId());
    UserPassWordDo userPassWordDo=convertPasswordFromDataObject(userModel);
    userpasswordDoMapper.insertSelective(userPassWordDo);
    return;
}

@Override
public UserModel validateLogin(String telphone, String encrptPassword) throws BusinessException {
    //通过用户手机获取用户信息
    UserDo userDo=userDoMapper.selectByTelphone(telphone);
    if (userDo==null){
        throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL  );
    }
    UserPassWordDo userPassWordDo=userpasswordDoMapper.selectByUserId(userDo.getId());
    UserModel userModel=convertFromDataObject(userDo,userPassWordDo);
    //比对用户信息内加密的密码是否和传输进来的密码相匹配
    if (!StringUtils.equals(encrptPassword,userModel.getEncrptPassword())){
        throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL  );
    }
    return userModel;
}

private UserPassWordDo convertPasswordFromDataObject(UserModel userModel){
    if (userModel==null){
        return null;
    }
    UserPassWordDo userPassWordDo=new UserPassWordDo();
    userPassWordDo.setEncrptPassword(userModel.getEncrptPassword());
    userPassWordDo.setUserId(userModel.getId());
    return userPassWordDo;
}


private UserDo convertFromDataObject(UserModel userModel){
    if (userModel==null){
        return null;
    }
    UserDo userDo=new UserDo();
    BeanUtils.copyProperties(userModel,userDo);
    return userDo;
}

private UserModel convertFromDataObject(UserDo userDo, UserPassWordDo userpasswordDo){
    if(userDo==null){
        return null;
    }
    UserModel userModel=new UserModel();
    BeanUtils.copyProperties(userDo,userModel);
    if(userpasswordDo!=null){
        userModel.setEncrptPassword(userpasswordDo.getEncrptPassword());
    }
    return userModel;
}

1 First, register (registration) method:
here we need to explain my user table does not contain the user's password, but wrote a separate user_password a table, as follows

Followed by a domain model UserModel user to contain all of the fields the user
public class UserModel {
Private ID Integer;
@NotBlank (Message = "User name can not empty")
Private String name;
@NotNull (Message = "Required Options Gender")
String Gender Private;
@NotNull (the Message = "Age is a required option")
@min (value = 0, the Message = "must be greater than 0 years of age")
@max (value = 150, the Message = "must be younger than 150 years old." )
Private Integer Age;
@NotNull (the Message = "phone number can not be empty")
Private String Cellphone;
Private String registerMode;
Private String thirdPartyId;
@NotNull (the Message = "password can not be blank")
Private String encrptPassword;
@NotNull (the Message = "phone number can not be empty")
Private String the ReceiverAddress;
Integral Integer Private;
GetSet omitted
Because the operation is a two tables, the custom convertPasswordFromDataObject a similar manner, the logic is very simple, and uses a BeanUtils.copyProperties (a, b) (assigned to a b).
Analysis of the code line by line. The first is the determination of empty UserModel processing, an exception, use ExceptionHandler capture, followed by verification of input registration information used here HibernateValidator.
Next, call the insert method mapper user interfaces UserPasswordDoMapper the mapper interfaces UserDoMapper and password, the logic here is simple, not repeat them.
Method 2 Log validateLogin
logical log is first obtained by a mobile phone number the user information, and then compare the user password is encrypted and password match the incoming transmission. Look at specific implementation code.

UserController

/ **
@Description: User login interfaces
@Param: user registration information
@return:
/
@RequestMapping ( "/ index")
public String index () {
return "ADMIN / adminHomepage";
}

@RequestMapping(value = "/login")
@ResponseBody
public CommonReturnType login(@RequestParam(name = "telphone") String telphone,
                    @RequestParam(name = "password") String password) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
    //入参校验
    if (org.apache.commons.lang3.StringUtils.isEmpty(telphone) ||
            StringUtils.isEmpty(password)) {
        throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
    }
    //用户登录服务,用来校验用户登录是否合法
    UserModel userModel = userService.validateLogin(telphone, this.EncodeByMd5(password));
    //将登录凭证加入到用户登陆成功的session内
    this.httpServletRequest.getSession().setAttribute("IS_LOGIN", true);
    this.httpServletRequest.getSession().setAttribute("LOGIN_USER", userModel);
    String url = "/shop/home";
    return CommonReturnType.create(url);
}

/**
*@Description:用户注册接口
*@Param:注册信息
*@return:
*/
@RequestMapping(value = "/register", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType register(@RequestParam(name = "telphone") String telphone,
                                 @RequestParam(name = "otpCode") String otpCode,
                                 @RequestParam(name = "name") String name,
                                 @RequestParam(name = "gender") String gender,
                                 @RequestParam(name = "password") String password,
                                 @RequestParam(name = "age") Integer age,
                                 @RequestParam(name = "receiverAddress") String receiverAddress) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
    //验证手机号和对应的otpCode相符合
    String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(telphone);
    if (!com.alibaba.druid.util.StringUtils.equals(otpCode, inSessionOtpCode)) {
        throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码不符合");
    }
    //用户的注册流程
    UserModel userModel = new UserModel();
    userModel.setName(name);
    userModel.setGender(gender);
    userModel.setAge(age);
    userModel.setTelphone(telphone);
    userModel.setRegisterMode("byphone");
    userModel.setEncrptPassword(this.EncodeByMd5(password));
    userModel.setReceiverAddress(receiverAddress);
    userService.register(userModel);
    return CommonReturnType.create(null);
}

1 Log in the Controller
the Controller in code written in a very clear (the beginning of the index () method can be ignored, this is what I wrote to jump back home), is also into the reference check (this is only sentenced empty), then calls the method of service layer login, login information is stored in the session finally, after the control state easily. Special note is the last CommonReturnType type, directly on the code:
Private String Status;
Private Data Object;
Private String URL;

/**
*@Description:定义一个通用的创建方法
*@Param:
*@return:
*/
public static CommonReturnType create(Object result){
    return CommonReturnType.create(result ,"success");
}

public static CommonReturnType create(String url){
    return CommonReturnType.create(null,"success",url);
}

public static CommonReturnType create(Object result,String status){
    CommonReturnType type=new CommonReturnType();
    type.setStatus(status);
    type.setData(result);
    return type;
}

public static CommonReturnType create(Object result,String status,String url){
    CommonReturnType type=new CommonReturnType();
    type.setStatus(status);
    type.setData(result);
    type.setUrl(url);
    return type;
}

getset omit
the class in front of the response packet, represents a generic return type, mainly by state status, data data constitute (the last attribute url is because my login page is a static page, and other pages I was using a template page write, so to force the front and rear end are not isolated, separate front and rear end if you want to write, you can not add). Creat class defines a method which, if the parameter is null, the default status is Success, and then rewritten into the reference method can fill.
2 registration controller
using annotations @RequestParam parameter injection, and then verify that the phone number and the corresponding otpCode compliance (otp SMS verification code behind to speak), and finally set the properties. Md5 encryption involved here, I have defined a method EncodeByMd5 same class as follows:
@ResponseBody
public EncodeByMd5 String (String STR) throws NoSuchAlgorithmException, UnsupportedEncodingException {
// determines the computing method
MessageDigest md5 = MessageDigest.getInstance ( "MD5" ) ;
Base64Encoder base64en new new Base64Encoder = ();
// encrypted string
string for newstr = base64en.encode (md5.digest (str.getBytes ( "UTF-. 8")));
return for newstr;
}
The next is the user interface to obtain short otp :
} I am here to otp code printed to the console, just to simulate SMS verification process. (This part of the Internet there are many, I also Zhaomaohuahu copy of)













Other content on the user's back-end module I feel no need to write, because the user backend modules are some simple crud operation, too much information on the Internet, very simple and very easy to grasp. Then here login register related to the capture and abnormal parameters into the check, the two parts you have to think the trouble can not directly write Login Register logic, but this design is far from perfect. The two parts of the Internet also has a lot of information, I will not repeat them.

Guess you like

Origin www.cnblogs.com/lwblwb/p/11453255.html