学成在线(后端开发)第一天

学完以下技术栈后,可进行本项目的学习
学成在线(后端开发)第一天_第1张图片
开始学习:

项目的简单介绍

从在线教育的火热到如今,在线教育的模式出现多种多样,包括:B2C、C2C、B2B2C等业务模式。学成在线采用B2B2C业务模式,即向企业或个人在线教育平台提供教学服务,老师和学生通过平台完成整个教学和学习的过程,市场上类似的平台有:网易云课堂、腾讯课堂等,学成在线的特点是IT职业课程在线教学。

学成在线包括在线教育平台、业务支持系统、基础服务来构建整个功能架构

架构图:
学成在线(后端开发)第一天_第2张图片
技术栈列表:

学成在线(后端开发)第一天_第3张图片

模块功能列表:

1.在线教育平台

功能模块名称 功能说明
门户 在首页、活动页、专题页等页面提供课程学习入口。
教学管理平台 教学机构登录系统的入口,通过此来管理机构中的课程相关的数据。
运营平台 教师登录教学管理中心进行课程管理、资源管理、考试管理等教学活动。

2.业务系统支撑

功能模块名称 功能说明
内容管理系统 内容管理中对教学机构的课程、课程计划、课程教师、课程营销数据进行管理
教学管理中心 对平台的入住教学机构数据进行管理和审核,以及课程中设计到的课程作业。
学习中心 对课程中的学员学习课程的记录数据来进行管理。
社交系统 论坛系统、问答系统、消息系统、评论系统等信息的管理
媒资管理 课程计划所关联的课程流媒体资源数据进行管理(直播、录播)。

3.基础服务

功能模块名称 功能说明
系统管理 对学成在线后端服务提供系统的基础数据。
支付系统 管理收费课程的交易记录和订单数据。
文件服务 管理系统中的文件资源,包括课程图片、教师图片等。
验证码服务 生成系统中的验证码并通过短息服务发送验证码、校验验证码等。
统一认证服务 对系统中的所有用户资源进行管理,并提供服务中用户资源的认证功能
视频点直播 在课程学习时需要通过此服务来对视频资源进行播放。

剩下的流程图、UML我就不介绍了,直接开始实战

环境搭建

导入linux镜像,并使用docker容器开启组件:
学成在线(后端开发)第一天_第4张图片
启动nginx导入前端页面:
学成在线(后端开发)第一天_第5张图片
配置访问host
前端项目中,各个页面跳转都是由域名构成。为了方便需要修改本机host地址。

进入C:\Windows\System32\drivers\etc目录,修改hosts文件。添加如下内容。温馨提示:做好备份

#门户网站域名
127.0.0.1 www.xuecheng.com
#企业管理后台
127.0.0.1 admin.xuecheng.com
#机构管理后台
127.0.0.1 manage.xuecheng.com

配置成功后,在浏览器打开http://admin.xuecheng.com即可进入企业管理后台页面

后端环境搭建

学成在线(后端开发)第一天_第6张图片
学成在线(后端开发)第一天_第7张图片
项目基于前后端分离的架构进行开发,前后端分离架构总体上包括前端和服务端,通常是多人协作开发

  • 前后端分离开发基于HTTP+JSON交互

  • 通过接口文档(API文档)定义规范

  • 前后端按照文档定义请求及响应数据

这里我们使用YAPI接口文档管理

登录功能

在写代码前,我们可以回想一下以前是怎么进行身份验证的?
没错 cookie 或session,但是对于前端来说,有移动端页面,h5页面,VUE页面,对于手机端页面可能就没有session,所以用这俩存登录信息,权限检验,就不行了
下面介绍一个新的身份校验工具——JWT
学成在线(后端开发)第一天_第8张图片
学成在线(后端开发)第一天_第9张图片
小实例:
首先导入依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

测试类:

@Test
public void testCreateToken() {
    //生成token
    //1 准备数据
    Map map = new HashMap();
    map.put("id",1);
    map.put("mobile","13800138000");
    //2 使用JWT的工具类生成token
    long now = System.currentTimeMillis();
    String token = Jwts.builder()
            .signWith(SignatureAlgorithm.HS512, "zjf") //指定加密算法
            .setClaims(map) //写入数据
            .setExpiration(new Date(now + 30000)) //失效时间
            .compact();
    System.out.println(token);
}

//解析token

/**
 * SignatureException : token不合法
 * ExpiredJwtException:token已过期
 */
@Test
public void testParseToken() {
    String token = "...";//这里面换成上面测试打印的token
    try {
        Claims claims = Jwts.parser()
                .setSigningKey("zjf")
                .parseClaimsJws(token)
                .getBody();
        Object id = claims.get("id");
        Object mobile = claims.get("mobile");
        System.out.println(id + "--" + mobile);
    }catch (ExpiredJwtException e) {
        System.out.println("token已过期");
    }catch (SignatureException e) {
        System.out.println("token不合法");
    }
}

基本介绍完毕, 下面完成登录功能:

学成在线(后端开发)第一天_第10张图片
接口文档:
学成在线(后端开发)第一天_第11张图片
学成在线(后端开发)第一天_第12张图片
需要使用的数据表:
学成在线(后端开发)第一天_第13张图片
后端代码显示:

web层:
学成在线(后端开发)第一天_第14张图片

package com.xuecheng.system.controller;

import com.xuecheng.commons.model.dto.LoginDto;
import com.xuecheng.commons.model.vo.ResponseResult;
import com.xuecheng.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {
    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseResult organizationLogin(@RequestBody LoginDto loginDto){
        return userService.organizationLogin(loginDto);
    }

}

service层:
学成在线(后端开发)第一天_第15张图片

public interface UserService extends IService<User> {

    ResponseResult organizationLogin(LoginDto loginDto);
}

serviceImpl层:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public ResponseResult organizationLogin(LoginDto loginDto) {
        if (StrUtil.isBlank(loginDto.getUsername())) {
            throw new BusinessException(ErrorCode.DATAERROR);
        }
        if (StrUtil.isBlank(loginDto.getPassword())) {
            throw new BusinessException(ErrorCode.DATAERROR);
        }
        if (StrUtil.isBlank(loginDto.getUtype())) {
            throw new BusinessException(ErrorCode.DATAERROR);
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, loginDto.getUsername());
        wrapper.eq(User::getUtype, loginDto.getUtype());
        User user = userMapper.selectOne(wrapper);
        if (BeanUtil.isEmpty(user)){
            User u = new User();
            u.setPhone(loginDto.getUsername());
            u.setPassword(DigestUtil.md5Hex(loginDto.getPassword()));
            u.setUtype(loginDto.getUtype());
            userMapper.insert(u);
        }
        if (!StrUtil.equals(DigestUtil.md5Hex(loginDto.getPassword()), user.getPassword())) {
            throw new BusinessException(ErrorCode.LOGINERROR);
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("userId",user.getId());
        map.put("companyId",user.getCompanyId());
        map.put("companyName",user.getCompanyName());
        String token = JwtUtils.createToken(map, 180);

        LoginVo loginVo = new LoginVo();
        loginVo.setAccess_token(token);
        loginVo.setUsername(user.getPhone());

        return ResponseResult.okResult(loginVo);

    }
}

mapper层:

public interface UserMapper extends BaseMapper<User> {

}

搭建网关

网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等。学成在线也是通过网关介入所有请求,进行路由转发学成在线(后端开发)第一天_第16张图片
学成在线(后端开发)第一天_第17张图片

统一异常处理

学成在线(后端开发)第一天_第18张图片
学成在线(后端开发)第一天_第19张图片

package com.xuecheng.web.exception;


import com.xuecheng.commons.enums.ErrorCode;
import lombok.Data;

@Data
public class BusinessException extends RuntimeException{

    private ErrorCode errorCode;

    public BusinessException(ErrorCode errorCode) {
        super(errorCode.getDesc());
        this.errorCode = errorCode;
    }
}
package com.xuecheng.web.exception;

import com.xuecheng.commons.enums.ErrorCode;
import com.xuecheng.commons.model.vo.ResponseResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalException {
    @ExceptionHandler(RuntimeException.class)
    public ResponseResult exception(RuntimeException e){
         e.printStackTrace();
         return ResponseResult.errorResult(ErrorCode.ERROR);
    }

    @ExceptionHandler(BusinessException.class)
    public ResponseResult  BusinessException(BusinessException e){
        ErrorCode errorCode = e.getErrorCode();
        return ResponseResult.errorResult(errorCode);
    }
}

结果展示:
登录成功会进入商家页面

学成在线(后端开发)第一天_第20张图片
创建git,以天为单位作为分支,提交到gitee上,用以练习git操作
学成在线(后端开发)第一天_第21张图片

第一天任务完成

你可能感兴趣的:(#,项目实战,java,运维,spring,boot,spring,cloud,分布式)