开发环境

开发工具:idea+MAVEN
数据库:mysql+redis
jdk版本:1.8
web容器:springboot自带的tomcat
预计用到的框架:springboot+spring cloud+mybatis
前端:由于不是很懂前端框架,准备百度找几个对应的模板(基础的jquery我还是会)

准备工作

1.先准备一个能用的idea
2.设计好相应的模块以及表,想好哪些模块可以独立为一个服务
3.还要找找资料写好的代码怎么上传到github.
如何将本地代码上传至github
https://github.com/TangXuesong/sso.git 这是我的github地址
4.项目服务图:

表设计思路以及详细内容

1.每个项目都需要有一个用户登录系统,那么不可或非需要一个用户表(由于只是简单的简历展示,
权限啥的就不弄了)
2.既然是简历展示系统,那么肯定要有与简历相关的表,比如说简历表/简历详细信息表/工作经验表/
项目经验表。(这是从51job添加简历时想到的,一个用户多个简历,每个简历有多个公司,每个公司
有多个项目经验).
每个表其实要弄很多个备用字段防止以后要修改表字段很麻烦,但是由于这是个人做的简易项目就不这
么弄了,还有索引啥的sql优化也就不考虑了,毕竟没那么大的数据量哈哈

TBL_CSM_USER(用户表):
UR_ID                       INT(11)         用户ID,主键自增
UR_NICKNAME                 VARCHAR(50)     用户昵称
UR_EMAIL                    VARCHAR(50)     注册邮箱(长度是自己估算的,没有那么认真去计较)
UR_PASSWORD                 VARCHAR(200)    用户密码
UR_SEX                      CHAR(1)         用户性别(0表示男/1表示女/默认是男)
UR_AGE                      INT(3)          用户年龄
UR_REGISTER_TIME            VARCHAR(30)     用户注册时间(yyyy-mm-dd HH:mm:ss格式)
TBL_RSM_RESUME(用户简历表):
RS_ID                       INT(11)         简历表ID,主键自增
RS_URID                     INT(11)         对应用户ID
RS_NAME                     VARCHAR(50)     简历名称
RS_CREATE_TIME              VARCHAR(30)     简历创建时间(yyyy-mm-dd HH:mm:ss格式)
RS_UPDATE_TIME              VARCHAR(30)     简历修改时间(yyyy-mm-dd HH:mm:ss格式)
RS_DEL_IND                  CHAR(1)         删除标志(Y表示是/N表示否)
TBL_RSM_RESDETAIL(简历详细信息表):
RL_ID                       INT(11)         简历详细信息表ID,主键自增
RL_RSID                     INT(11)     对应简历ID
RL_NAME                     VARCHAR(50)     姓名
RL_SEX                      CHAR(1)         性别(0表示男/1表示女/默认是男)
RL_BIRTH                    VARCHAR(11)     生日(YYYY-MM-DD)
RL_LOCAL                    VARCHAR(20)     所在地
RL_EMAIL                    VARCHAR(50)     邮箱
RL_PHONE                    VARCHAR(20)     联系电话(设置成varchar是因为可能会有021-xxxx这样子)
RL_CURREV                   DOUBLE(11,2)    目前月收入
RL_EXPREV                   DOUBLE(11,2)    期望月收入
RL_SLFINR                   VARCHAR(500)    自我介绍
RL_OCCUPATION               VARCHAR(20)     职业
RL_SCHOOL                   VARCHAR(50)     毕业院校(偷懒,毕业时间,院校类型,专业都用这一个字段)
RL_CREATE_TIME              VARCHAR(30)     简历详细信息创建时间(yyyy-mm-dd HH:mm:ss格式)
RL_UPDATE_TIME              VARCHAR(30)     简历详细信息修改时间(yyyy-mm-dd HH:mm:ss格式)
TBL_RSM_WORKEXP(工作经验表):
WP_ID                       INT(11)         工作经验表ID,主键自增
WP_RLID                     INT(11)     对应简历ID
WP_COMPNAME                 VARCHAR(100)    公司名称
WP_STARTTIME                VARCHAR(20)     开始工作时间(YYYY-MM)
WP_ENDTIME                  VARCHAR(20)     结束工作时间(YYYY-MM)
WP_OCCUPATION               VARCHAR(20)     在该公司的职业
WP_WORKCONTEXT              VARCHAR(300)    工作描述
WP_CREATE_TIME              VARCHAR(30)     工作经验创建时间(yyyy-mm-dd HH:mm:ss格式)
WP_UPDATE_TIME              VARCHAR(30)     工作经验修改时间(yyyy-mm-dd HH:mm:ss格式)
TBL_RSM_PROJEXP(项目经验表):
PP_ID                       INT(11)         项目经验表ID,主键自增
PP_WPID                     INT(11)         对应工作经验ID
PP_NAME                     VARCHAR(20)     项目名称
PP_STARTTIME                VARCHAR(20)     项目开始时间(YYYY-MM)
PP_ENDTIME                  VARCHAR(20)     项目结束时间(YYYY-MM)
PP_PROJDESC                 VARCHAR(300)    项目描述
PP_WORKDESC                 VARCHAR(500)    项目中个人职业描述
PP_CREATE_TIME              VARCHAR(30)     项目经验创建时间(yyyy-mm-dd HH:mm:ss格式)
PP_UPDATE_TIME              VARCHAR(30)     项目经验修改时间(yyyy-mm-dd HH:mm:ss格式)

开始开发

1.用idea先新建一个Maven项目,名称叫resume.

2.在该项目基础上新建一个spring cloud eureka-server工程

 1.建好以后需要配置application.yml文件指定端口,服务名称.在启动类上加上注解@EurekaServerApplication,表明该服务是一个EurekaServer服务.

3.新建一个resume-user工程(表明该工程提供用户服务)

 1.会用springboot/mybatis/web/eureka/rabbitmq到/2.建好以后需要配置application.yml文件指定端口,服务名称,在启动类上加上注解@EnableEurekaClient表明该服务是一个EurekaClient服务

4.以相同步骤新建两个工程resume-email/resume-center(邮箱发送和简历中心)

整体结构截图如下:

4.开始开发

1.配置mysql数据源,利用mybatis-generator生成相关mapper.xml和mapper.java文件.
2.配置redis
3.调试html文件做到能用的地步(这个花了我一下午)
4.先做注册功能,注册肯定是需要邮箱发送验证码的,具体代码如下:
Controller层:

    //发送验证码@RequestMapping("sendEmail")public String sendEmail(HttpSession session, String email) {String code = userService.sendEmail(email);if (code.equals("false")) {return "false";}HashMap<String, String> map = new HashMap<>();logger.info("email------:"+email+"---------code-------:"+code);map.put(email, code);session.setAttribute("regCode", map);return "true";}

Service层:

    //发送注册邮件@Overridepublic String sendEmail(String email) {//先校验邮箱格式是否正确if (!email.matches("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+")) {return "false";}//先查询数据库,校验该邮箱是否已经注册.TblCsmUser user = tblCsmUserMapper.selectByEmail(email);if(user!=null)return "false";//生成六位数作为验证码String code = CodeUtils.createCode();//此处调用rabiitMQ通知邮箱服务发送邮件给对应邮箱.return code;}

Mapper层:

  <select id="selectByEmail" resultMap="BaseResultMap" parameterType="java.lang.String" >select<include refid="Base_Column_List" />from tbl_csm_userwhere UR_EMAIL = #{email,jdbcType=VARCHAR}</select>

以上是发送验证码功能(RABBITMQ部分得等我学会了再加上去,哈哈.目前就大概了解是个消息中间件,用来异步发送消息,节省时间)
接下来是注册功能:
Controller层:

    //注册@RequestMapping("register")public String register(HttpSession session, String email, String code, String password, String name) {//先从session中取出regCodeMapHashMap<String, String> regCode = (HashMap<String, String>) session.getAttribute("regCode");if (regCode == null)return "codeError";return userService.register(regCode, email, name, code, password);}

Service层:

 //注册账号@Overridepublic String register(HashMap<String, String> regCode, String email, String name, String code, String password) {//先校验验证码和邮箱是否正确String sendCode = regCode.get(email);if(!code.equals(sendCode))return "codeError";//正确的情况下查询数据库该邮箱是否已经注册过TblCsmUser dbUser = tblCsmUserMapper.selectByEmail(email);if(dbUser!=null)return "hasError";//没有注册过则添加该用户TblCsmUser user=new TblCsmUser();user.setUrAge(20); //默认20user.setUrEmail(email);//注册邮箱user.setUrNickname(name);//用户昵称user.setUrRegisterTime(DateUtils.getCurrDatetoHHmmss()); //当前系统时间戳user.setUrSex("0"); //默认是男user.setUrPassword(MD5Utils.inputPassToFormPass(password));tblCsmUserMapper.insertSelective(user);return "true";}

5.注册功能写完以后该做登录了,登录实现逻辑挺简单,但是考虑到要做单点登录,所以注释较多,我想了很久差点没绕出来:
Controller层:

    //登录@RequestMapping("login")public String login(HttpServletResponse response, HttpSession session, String email, String password) {String result= userService.login(email, password);if(result.equals("false"))return "false";//写入redis数据库,将该token以及用户信息redisTemplate.opsForValue().set("user"+session.getId(),result,1800,TimeUnit.MINUTES);//写入session以示登录成功session.setAttribute("user",result);return session.getId();}

Service层:

    //登录@Overridepublic String login(String email, String password) {//1.从数据库中获取该邮箱对应的用户TblCsmUser dbUser = tblCsmUserMapper.selectByEmail(email);if(dbUser==null)return "false";if(!dbUser.getUrPassword().equals(MD5Utils.inputPassToFormPass(password)))return "false";return JSON.toJSONString(dbUser);}

以上完成后其实用户就可以正常登录了(Cookie写入方法就不贴了,redis的使用推荐一个博客,简单易懂)
Springboot使用redis详解
接下来首先要考虑的是做简历中心(展示修改简历)到登录中心的一个登录过程,目前思路如下:

1.用户首次访问简历中心,简历中心拦截器校验会先调用登录中心的一个接口查看用户是否登录(这个接口的任务
应该是:获取cookie->没有cookie返回false->获取token,拿token去redis中查找->redis没有数据返回
false->redis有数据返回token给简历中心)
2.简历中心如果接收到返回的是false,则跳转到登录中心的登录界面去登录,如果接受到的是token,就拿该token
去redis中查找用户信息,如果没有找到就重复1步骤,找到的话就将该token存入session.(想到这里第1步
之前应该还有个步骤,那就是从session中获取token,如果没有token就照第1步,如果有token那就去redis
中查一下校验该token是否过期,没有过期的话就不会被拦截器拦截了)

以上涉及微服务之间调用接口,又得找资料学习一下

单点登录实现方式:
简历中心写一个拦截器,代码如下:

package com.txs.resume.resumecenter.interceptor;import com.alibaba.fastjson.JSON;
import com.txs.resume.resumecenter.pojo.TblCsmUser;
import com.txs.resume.resumecenter.utils.RestCallUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;/*
*
* 使用拦截器校验该用户是否登录
*
* */
@Component
public class LoginInterceptor implements HandlerInterceptor {private Logger logger= LogManager.getLogger(LoginInterceptor.class.getName());@Autowiredprivate LoadBalancerClient loadBalancerClient;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {logger.info("进入到简历中心拦截器");Object user = request.getSession().getAttribute("resUser");logger.info(user);//先检查是否有用户登录信息,有就让其通过.if(user!=null){return true;}//检查登录中心返回的token是否有效,String token=request.getParameter("token");if(token!=null){//用该token去redis数据库查询取到对应的用户信息,存放在session中表示局部变量String userJson = stringRedisTemplate.opsForValue().get("user" + token);TblCsmUser csmUser = JSON.parseObject(userJson,TblCsmUser.class);request.getSession().setAttribute("resUser",csmUser);return true;}//获取登录中心的登录地址跳转过去进行登录并带上返回地址ServiceInstance serviceInstance = loadBalancerClient.choose(RestCallUtils.USERSERVICE);String redirect_uri=request.getRequestURL().toString();logger.info(redirect_uri);response.sendRedirect("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/login.html?redirect_uri="+redirect_uri);return false;}
}

登录中心也写一个拦截器:

package com.txs.resume.resumeuser.interceptor;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*
*
* 使用拦截器校验该用户是否登录
*
* */
@Component
public class LoginInterceptor implements HandlerInterceptor {private Logger logger= LogManager.getLogger(LoginInterceptor.class.getName());@Autowiredprivate LoadBalancerClient loadBalancerClient;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {logger.info("进入到登录中心拦截器");Object user = request.getSession().getAttribute("user");//判断是否已经登录过,如果没有登录就放行去登录界面.logger.info(user);if(user==null){return true;}//登陆过就直接获取token并返回给简历中心String token = request.getSession().getId();logger.info(token);String redirect_url = request.getParameter("redirect_url");logger.info(redirect_url);response.sendRedirect(redirect_url+"?token="+token);return false;}
}

因为现在找工作第一,这个项目的简历模块就先搁置(毕竟是简单的增删改查),把注册模块的发送邮件集成为RABBITMQ再弄

1.邮箱服务代码如下:

package com.txs.resume.resumeemail.utils;import jdk.nashorn.internal.runtime.logging.Logger;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;@Component
@RabbitListener(queues = "email")
public class EmailListener {@AutowiredJavaMailSender javaMailSender;@RabbitHandlerpublic void sendEmail(HashMap<String, String> map) {System.out.println("发送验证码");String email = map.get("email");String code = map.get("code");SimpleMailMessage msg=new SimpleMailMessage();msg.setSubject("注册松松松简历系统验证码");msg.setFrom("t943044085@163.com");msg.setTo(email);msg.setText("您的验证码为:"+code);msg.setSentDate(new Date());javaMailSender.send(msg);}}

2.application.yml配置如下:

spring:application:name: resume-emailmail:host: smtp.163.comusername: t943044085@163.compassword: RIBQYMASMCALNPARdefault-encoding: UTF-8protocol: smtpport: 25rabbitmq:host: localhostport: 5672username: guestpassword: guestvirtual-host: /test

3.用户中心配置rabbitMq代码如下:

package com.txs.resume.resumeuser.rabbit;import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;@Configuration
public class RabbitmqConfiguration {@Autowiredprivate RabbitTemplate rabbitTemplate;@PostConstructpublic void initRabbitTemplate() {// 设置生产者消息确认rabbitTemplate.setConfirmCallback(new RabbitConfirmCallback());}/*** 申明队列** @return*/@Beanpublic Queue queue() {Map<String, Object> arguments = new HashMap<>(4);// 申明死信交换器arguments.put("x-dead-letter-exchange", "exchange-dlx");return new Queue("email", true, false, false, arguments);}/*** 没有路由到的消息将进入此队列** @return*/@Beanpublic Queue unRouteQueue() {return new Queue("queue-unroute");}/*** 死信队列** @return*/@Beanpublic Queue dlxQueue() {return new Queue("dlx-queue");}/*** 申明交换器** @return*/@Beanpublic Exchange exchange() {Map<String, Object> arguments = new HashMap<>(4);// 当发往exchange-rabbit-monitor的消息,routingKey和bindingKey没有匹配上时,将会由exchange-unroute交换器进行处理arguments.put("alternate-exchange", "exchange-unroute");return new DirectExchange("exchange-email", true, false, arguments);}@Beanpublic FanoutExchange unRouteExchange() {// 此处的交换器的名字要和 exchange() 方法中 alternate-exchange 参数的值一致return new FanoutExchange("exchange-unroute");}/*** 申明死信交换器** @return*/@Beanpublic FanoutExchange dlxExchange() {return new FanoutExchange("exchange-dlx");}/*** 申明绑定** @return*/@Beanpublic Binding binding() {return BindingBuilder.bind(queue()).to(exchange()).with("email").noargs();}@Beanpublic Binding unRouteBinding() {return BindingBuilder.bind(unRouteQueue()).to(unRouteExchange());}@Beanpublic Binding dlxBinding() {return BindingBuilder.bind(dlxQueue()).to(dlxExchange());}
}

上面是申明相应的rabbitmq队列与交换机,向队列发送消息很简单,一句话:

        //此处调用rabiitMQ通知邮箱服务发送邮件给对应邮箱.Map<String,String> map = new HashMap<>();map.put("email", email);map.put("code", code);rabbitTemplate.convertAndSend("email", map);

利用springcloud搭建一个简易的分布式简历展示系统相关推荐

  1. 利用SpringCloud搭建一个最简单的微服务框架

    利用SpringCloud搭建一个最简单的微服务框架 https://blog.csdn.net/caicongyang/article/details/52974406 1.微服务 微服务主要包含服 ...

  2. 如何快速搭建一个简易的ELK日志分析系统

    一.ELK简介   ELK就是一款非常优秀的.开源的.用于搭建实时日志分析平台的组件.ELK是Elasticsearch.Logstash和Kiabana这3款开源框架首字母的缩写.通过这三个组件,构 ...

  3. 使用Java语言搭建一个简易的局域网直播(live)系统

    演示一下 局域网直播系统,顾名思义是运行在局域网中的系统,整个直播系统由两部分构成:录制和播放,核心思路是推拉流和流转码. 录制直播 录制直播使用的是自己电脑的摄像头和麦克风,使用Java自带的JFr ...

  4. 如何搭建一个简易的Web框架

    Web框架本质 什么是Web框架, 如何自己搭建一个简易的Web框架?其实, 只要了解了HTTP协议, 这些问题将引刃而解. 简单的理解:  所有的Web应用本质上就是一个socket服务端, 而用户 ...

  5. SpringBoot + Dubbo + Zookeeper搭建一个简单的分布式服务

    本文使用SpringBoot + Dubbo + Zookeeper 来搭建一个简单的分布式服务 文章目录 dubbo-spring-boot-starter 如何发布 Dubbo 服务 如何消费 D ...

  6. 10分钟利用django搭建一个博客

    以前老是听说ROR开发有多快多块,网上还有朋友为了证明这,专门制作了10分钟利用rails框架搭建一个简易博客的教程,最近学习django框架,觉得django给开发者的便捷也很多,心血来潮来写个10 ...

  7. python云服务器搭建教程_Python利用flask搭建一个共享服务器的步骤

    这篇文章我们来讲一下在网站建设中,Python利用flask搭建一个共享服务器的步骤.本文对大家进行网站开发设计工作或者学习都有一定帮助,下面让我们进入正文. 零.概述 我利用flask搭建了一个简易 ...

  8. 抛开vue-cli 利用requireJS搭建一个vue项目

    ---恢复内容开始--- 现在学习vue都是利用脚手架vue-cli快速搭建一个项目,这是非常高效的方法,我是十分推荐的,但是有时候在没有互联网的情况,我们没办法在node环境下,敲一个nmp ins ...

  9. 利用Octopress搭建一个Github博客

    小引 Octopress是利用Jekyll博客引擎开发的一个博客系统,生成的静态页面能够很好的在github page上展现.号称是hacker专属的一个博客系统(A blogging framewo ...

最新文章

  1. python创建excel图表_Python:使用图表创建Excel工作表
  2. 淘宝2011.9.21校园招聘会笔试题
  3. c++primer书上习题date类的部分源代码(待整理)
  4. vue 定义全局弹框_用vue/react写一个全局提示弹框
  5. 求解哈夫曼编码Java实现,用Java实现哈夫曼编码解决方法
  6. python安装Scrapy踩过的坑以及安装指导
  7. tableView 获取网络图片,并且设置为圆角(优化,fps)
  8. [译]GLUT教程 - 笔划字体
  9. 如何在VC环境下使用Halcon库
  10. 如何自学python知乎-马哥教育官网-专业Linux培训班,Python培训机构
  11. 计算机网路网络层之DHCP协议
  12. Vim配置Java IDE
  13. python分支语句中if和else必须同时出现吗_多分支决策必须采用嵌套的if-else语句实现: A、 对 B、 错_学小易找答案...
  14. 技术资源分享(更新中)
  15. 【社会相关】:大神写的考研政治复习攻略
  16. 【Linux】一步一步学Linux系列教程汇总(更新中......)
  17. 第一行代码:知晓当前是哪个界面
  18. Oracle Database 11g Release 2认证支持的操作系统版本跨度很大
  19. 百度地图有了这么有趣的功能
  20. 电大计算机基础期末考试题库,中央电大计算机基础考试题库大全

热门文章

  1. 无线控制需要服务器,H3C无线控制器与LDAP服务器配合进行远程Portal认证可以做么?...
  2. 关于Caused by: com.alibaba.fastjson.JSONException: syntax error, expect }, actual ,
  3. 分享79个ASP江湖论坛源码,总有一款适合您
  4. UE4元数据关键字的应用与含义,函数的标记和特殊使用(三)
  5. java注解与APT技术
  6. neo4j 社区版主从集群
  7. 递归找到节点后跳出递归循环
  8. 带社交分享的雨滴404错误页面源码
  9. adams和matlab联合仿真的书,MATLAB和ADAMS联合仿真
  10. 著名弹跳训练法 练成可提高30cm