Graduation Design: Based on Springboot to achieve job-hunting, campus recruitment system

Author Homepage: Programming Compass

 Introduction: high-quality creators in the Java field, CSDN blog experts Java projects, resume templates, learning materials, interview question bank, technical mutual assistance

Get the source code at the end of the article

content

1. Project Overview ...................................................................... ...................................................... ............ 3

2. Demand Analysis ................................................ ...................................................... ............ 3

2.1 Functional requirements...................................................................... ...................................................... ............ 3

2.2 Performance Requirements ................................................ ...................................................... ............ 10

3. Database Design ................................................................ ...................................................... ........ 10

3.1 Entity Relationship Diagram...................................................... ...................................................... ......... 10

3.2 Database table design...................................................................... ...................................................... ...... 10

4. Detailed Design ................................................................ ...................................................... ............ 10

4.1 Login Design...................................................... ...................................................... ............ 10

4.2 Order management...................................................................... ...................................................... ............ 11

5. System interface...................................................................... ...................................................... ............ 11

5.1 Related Interfaces...................................................................... ...................................................... ...................... 11

6. Experience and experience ................................................ ...................................................... ............ 12

1. Project overview:

   This project develops and implements a job-hunting website based on Springboot. The system is divided into front-end job-hunting and back-end data management. It is mainly divided into four corners: administrator, job seeker, company administrator, and company HR. Different roles enter the system and have different functional operations. User identity can be set in the background management. The system functions are complete, the interface is beautiful and generous, and it is suitable for graduation design.

Operating environment:

Development tools: IDEA or ECLIPSE

Database: MYSQL+REDIS

Development technology: Springboot+mybatis+mybatisPlus+shiro

Front-end development: AJAX+Jquery+layui

2.1 Functional requirements

2.1.1 System Division

 

2.1.1.1 User role division

  1. job seeker

A user who logs in to this website can retrieve and view the companies that the website has settled in and the job information posted by them, create their own resumes, and contact recruiters.

  1. Applicants

       2.1、HR

              A certain HR under the company can post new jobs and cancel the job postings posted by themselves

       2.2, company administrator

              Company administrator, fill in the relevant information of the company and become this role after entering the website, and can manage all positions published by the company, as well as manage all employees

3. Administrator

You can view relevant data on the site, manage private messages, systems, and settings.

2.1.1.2 Use case diagram and description of foreground service

  1. Recruiter Features

  1. View personal information: View the basic information and modification of your account
  2. Change Password: Change the login password of your account
  3. Private message: private message with job seekers
  4. Company entry: If it is the first time to log in to the website, the user can enter the company information, enter the website, and then post a job
  5. Post management: post, cancel, edit, etc.
  6. Employee management: under the premise of permission, manage all hrs in your company
  7. HR Information: View your own basic information
  1. Job Seeker Features:

 

  1. View personal information: View the basic information and modification of your account
  2. Change Password: Change the login password of your account
  3. Private Message: Contact HR for interested positions
  4. Personal Resume: Create your own resume for HR to view
  5. Job Search: Search for jobs you are interested in
  6. Search for companies: Search for companies you are interested in

2.1.1.3 Administrator background use case diagram

 

  1. View personal information: View the basic information and modification of your account
  2. Change Password: Change the login password of your account
  3. Company management: manage all the companies in the station
  4. User management: manage all users in the station
  5. Post management: manage all posts in the station
  6. Resume management: manage all resumes in the station
  7. Data dictionary: manage the data dictionary in the site
  8. Private message management: View chat relationships, chat records, etc. of all users

    3. Database Design

    3.1 Entity Relationship Diagram

    Table structure briefly

5. System interface

  1.  front page:

 

2. Login interface:

 3. Registration interface

 4. Job View Search

 

 5. Company view interface

6. HR management interface

 

 7. Post management interface

 8. Staff management

9. Resume

 

10. Administrator background management

 

 The core code of the system part:

package com.iurac.recruit.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.iurac.recruit.entity.Job;
import com.iurac.recruit.entity.User;
import com.iurac.recruit.exception.ManageException;
import com.iurac.recruit.security.RedisCacheManager;
import com.iurac.recruit.service.UserService;
import com.iurac.recruit.util.ImageUtil;
import com.iurac.recruit.util.Result;
import com.iurac.recruit.util.SaltUtil;
import com.iurac.recruit.util.TableResult;
import com.iurac.recruit.vo.PageResultVo;
import com.sun.org.apache.regexp.internal.RE;
import com.sun.org.apache.xpath.internal.operations.Mult;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Objects;

@Controller
public class UserController {

    @Autowired
    private RedisCacheManager redisCacheManager;
    @Autowired
    private UserService userService;


    @GetMapping({"/","/index"})
    public String toIndex(Model model){
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if(ObjectUtil.isNotNull(user)){
            model.addAttribute("userInfo",user);
        }

        return "index";
    }

    @GetMapping("/login")
    public String toLogin(){
        return "login";
    }

    @GetMapping("/register")
    public String toRegister(){
        return "register";
    }

    @PostMapping("/login")
    @ResponseBody
    public Result login(String username, String password, String code, HttpSession session) {
        String codes = (String) session.getAttribute("KAPTCHA_SESSION_KEY");
        if (StrUtil.hasBlank(codes)) {
            throw new RuntimeException("验证码已超时!");
        }

        String msg = "";
        try {
            if (codes.equalsIgnoreCase(code)){
                //获取主体对象
                Subject subject = SecurityUtils.getSubject();
                subject.login(new UsernamePasswordToken(username, password));
                return Result.succ("登录成功");
            }else{
                throw new RuntimeException("验证码错误!");
            }
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            msg="用户名错误!";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            msg="密码错误!";
        }catch (Exception e){
            e.printStackTrace();
            msg=e.getMessage();
        }
        return Result.fail(msg);
    }

    @GetMapping("logout")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }

    @PostMapping("/register")
    @ResponseBody
    public Result register(User user, @RequestParam("role")String role) throws Exception {
        user.setImg("default.png");
        userService.register(user,role);
        return Result.succ("操作成功");
    }

    @PostMapping("/user/update")
    @ResponseBody
    public Result updateUserInfo(@RequestParam(value = "phone",required = false) String phone,
                                 @RequestParam(value = "email",required = false) String email,
                                 @RequestParam(value="imgFile",required = false) MultipartFile file) throws Exception {
        User user = (User) SecurityUtils.getSubject().getPrincipal();

        redisCacheManager.getCache("authenticationCacheName").remove(user);
        if(!StrUtil.hasBlank(phone)){
            if(ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
                user.setPhone(phone);
            }else {
                return Result.fail("请输入正确的手机号");
            }
        }
        if(!StrUtil.hasBlank(email)){
            if(ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
                user.setEmail(email);
            }else {
                return Result.fail("请输入正确的邮箱地址");
            }
        }

        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            String imgName = user.getImg().equals("default.png")?ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))): user.getImg();
            user.setImg(imgName);
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }

        if(!userService.updateById(user)){
            return Result.fail("系统错误");
        }
        redisCacheManager.getCache("authenticationCacheName").put(user.getUsername(),user);
        return Result.succ("操作成功");
    }

    @PutMapping("/user/updatePassword/{password}")
    @ResponseBody
    public Result updateUserInfo(@PathVariable("password") String password) throws Exception {
        User user = (User) SecurityUtils.getSubject().getPrincipal();

        if(ReUtil.isMatch("[\\S]{6,12}", password)) {
            Md5Hash md5Hash = new Md5Hash(password,user.getSalt(),1024);
            if(md5Hash.toHex().equals(user.getPassword())){
                return Result.fail("请输入新密码");
            }
            redisCacheManager.getCache("authorizationCacheName").remove(user.toString());
            redisCacheManager.getCache("authenticationCacheName").remove(user);
            user.setPassword(md5Hash.toHex());
            System.out.println(user.getPassword());
        }else {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }

        if(!userService.updateById(user)){
            return Result.fail("系统错误");
        }
        redisCacheManager.getCache("authenticationCacheName").put(user.getUsername(),user);
        return Result.succ("操作成功");
    }

    @RequiresRoles("admin")
    @ResponseBody
    @GetMapping("/user/getByCondition")
    public TableResult<User> getByCondition(@RequestParam("page")Long page, @RequestParam("limit")Long limit,
                                           @RequestParam("username")String username, @RequestParam("role")String role,
                                           @RequestParam("startDate")String startDate, @RequestParam(value = "endDate",required = false)String endDate,
                                           @RequestParam("locked")String locked){
        PageResultVo<User> pageResultVo = userService.getByCondition(page,limit,username,role,locked,startDate,endDate);
        return new TableResult(0,"",pageResultVo.getTotal(),pageResultVo.getRecords());
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/save")
    public Result saveUser(@RequestParam("username")String username, @RequestParam("role")String[] role,
                             @RequestParam("password")String password, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                             @RequestParam("phone")String phone, @RequestParam("email")String email) throws IOException, ManageException {
        if(StrUtil.hasEmpty(username,password,phone,email) || role.length<=0){
            return Result.fail("请输入完整信息,避免输入空格");
        }
        if(!ReUtil.isMatch("[\\S]{6,12}", password)) {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
            return Result.fail("请输入正确的邮箱地址");
        }

        User user = new User();
        user.setId(IdUtil.simpleUUID());
        user.setUsername(username);
        user.setCreateTime(DateUtil.now());
        user.setSalt(SaltUtil.getSalt(8));
        Md5Hash md5Hash = new Md5Hash(password, user.getSalt(), 1024);
        user.setPassword(md5Hash.toHex());
        user.setLocked("0");
        user.setPhone(phone);
        user.setEmail(email);

        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            user.setImg(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }else {
            user.setImg("default.png");
        }

        userService.saveUser(user,role);
        return Result.succ("操作成功");
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/update/{id}")
    public Result updateUser(@PathVariable("id")String id,@RequestParam("role")String[] role,
                             @RequestParam("password")String password, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                             @RequestParam("phone")String phone, @RequestParam("email")String email) throws IOException, ManageException {
        if(StrUtil.hasEmpty(password,phone,email) || role.length<=0){
            return Result.fail("请输入完整信息,避免输入空格");
        }
        if(!ReUtil.isMatch("[\\S]{6,12}", password)) {
            return Result.fail("密码必须6到12位,且不能出现空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", phone)) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", email)){
            return Result.fail("请输入正确的邮箱地址");
        }

        User user = userService.getById(id);
        redisCacheManager.getCache("authorizationCacheName").remove(user.toString());
        redisCacheManager.getCache("authenticationCacheName").remove(user);

        user.setSalt(SaltUtil.getSalt(8));
        Md5Hash md5Hash = new Md5Hash(password, user.getSalt(), 1024);
        user.setPassword(md5Hash.toHex());
        user.setPhone(phone);
        user.setEmail(email);

        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            user.setImg(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,user.getImg(),"userIcon");
        }

        userService.updateUser(user,role);
        return Result.succ("操作成功");
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/delete/{id}")
    public Result deleteUser(@PathVariable("id")String id) throws  ManageException {
        userService.deleteUser(id);
        return Result.succ("操作成功");
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/user/lock/{id}")
    public Result lockUser(@PathVariable("id")String id) throws  ManageException {
        User user = userService.getById(id);
        user.setLocked("1".equals(user.getLocked())?"0":"1");
        userService.updateById(user);
        return Result.succ("操作成功");
    }
}

package com.iurac.recruit.controller;


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iurac.recruit.entity.Company;
import com.iurac.recruit.entity.Resume;
import com.iurac.recruit.entity.User;
import com.iurac.recruit.exception.ManageException;
import com.iurac.recruit.service.ResumeService;
import com.iurac.recruit.util.ImageUtil;
import com.iurac.recruit.util.Result;
import com.iurac.recruit.util.TableResult;
import com.iurac.recruit.vo.PageResultVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import org.springframework.stereotype.Controller;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author iurac
 * @since 2021-06-03
 */
@Controller
public class ResumeController {

    @Autowired
    private ResumeService resumeService;


    @PostMapping("/resume/saveOrUpdate")
    @ResponseBody
    public Result saveOrUpdate(Resume resume,
                                 @RequestParam(value="imgFile",required = false) MultipartFile file) throws Exception {

        if(StrUtil.hasBlank(resume.getName(),resume.getTechnology(),resume.getSalary(), resume.getMajor(),resume.getJob(),
                resume.getIntroduction(),resume.getExperience(),resume.getCollege(),resume.getBirth(),resume.getEducation(),
                resume.getPolitical(),resume.getMarriage(),resume.getSex())){
            return Result.fail("请输入完成信息,避免输入空格");
        }
        if(!ReUtil.isMatch("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}", resume.getPhone())) {
            return Result.fail("请输入正确的手机号");
        }
        if(!ReUtil.isMatch("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}", resume.getEmail())){
            return Result.fail("请输入正确的邮箱地址");
        }

        User user = (User) SecurityUtils.getSubject().getPrincipal();
        resume.setUserId(user.getId());

        QueryWrapper<Resume> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getId());
        Resume exitedResume = resumeService.getOne(queryWrapper);
        resume.setPhoto("default.png");

        boolean isUpdate = true;
        if(ObjectUtil.isNull(exitedResume)){//判断是新增还是更新
            resume.setId(IdUtil.simpleUUID());
            isUpdate = false;
        }else {
            resume.setId(exitedResume.getId());
            resume.setPhoto(exitedResume.getPhoto());
        }

        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            String photoName = resume.getPhoto().equals("default.png")?ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))): resume.getPhoto();
            resume.setPhoto(photoName);
            ImageUtil.saveImage(file,resume.getPhoto(),"photo");
        }

        boolean flag = isUpdate?resumeService.updateById(resume):resumeService.save(resume);

        if(flag){
            return Result.succ("操作成功");
        }else {
            return Result.fail("系统错误");
        }
    }


    @RequiresRoles("admin")
    @ResponseBody
    @GetMapping("/resume/getByCondition")
    public TableResult<Resume> getByCondition(@RequestParam("page")Long page, @RequestParam("limit")Long limit,
                                               @RequestParam("username")String username){
        PageResultVo<Resume> pageResultVo = resumeService.getByCondition(page,limit,username);
        return new TableResult(0,"",pageResultVo.getTotal(),pageResultVo.getRecords());
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/resume/update/{id}")
    public Result updateResume(@PathVariable("id")String id, @RequestParam(value = "imgFile",required = false) MultipartFile file,
                               Resume resume) throws IOException {
        if(StrUtil.hasEmpty(resume.getSex(),resume.getMarriage(),resume.getPolitical(),resume.getEducation(),
                resume.getEmail(),resume.getAge(),resume.getPhone(),resume.getName(),resume.getExperience(),
                resume.getTechnology(),resume.getSalary(),resume.getMajor(),resume.getIntroduction(),resume.getCollege(),
                resume.getBirth(),resume.getJob())){
            return Result.fail("请输入完整信息,避免输入空格");
        }

        Resume exitedResume = resumeService.getById(id);
        resume.setId(id);
        resume.setUserId(exitedResume.getUserId());
        resume.setPhoto(exitedResume.getPhoto());
        if(ObjectUtil.isNotNull(file) && !file.isEmpty()){
            String originalFileName = file.getOriginalFilename();
            resume.setPhoto(ImageUtil.getFileName(originalFileName.substring(originalFileName.lastIndexOf("."))));
            ImageUtil.saveImage(file,resume.getPhoto(),"companyIcon");
        }
        return resumeService.updateById(resume)?Result.succ("操作成功"):Result.fail("操作失败");
    }

    @RequiresRoles("admin")
    @ResponseBody
    @PostMapping("/resume/delete/{id}")
    public Result deleteResume(@PathVariable("id")String id) {
        resumeService.removeById(id);
        return Result.succ("操作成功");
    }

    /**
     *
     * @param id  用户ID
     * @param model
     * @return
     */
    @RequiresUser
    @GetMapping("/resume/detail/{id}")
    public String detail(@PathVariable("id")String id, Model model) {
        Resume resume = resumeService.getByUserId(id);
        model.addAttribute("resumeInfo",resume);
        return "service/detail_resume";
    }
}

Guess you like

Origin blog.csdn.net/whirlwind526/article/details/123323601