SpringBoot项目整理

项目介绍:

用SpringBoot实现一个员工管理系统

一、准备工作

1.1 这部分素材来源于BootStrap网站https://getbootstrap.com/docs/4.0/examples/
1.2 创建数据库
1.3 创建一个SpringBoot项目,并配置好相应的环境

二、首页实现

这里涉及静态资源导入的问题,通过查看源码,可以得知,只有在

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public

才可以默认导入,在本次项目中,将静态资源(页面)放到/resources/templates下,可以通过以下两种方式配置来进行访问:

  1. Controller中配置
  2. 自定义WebMvcConfigurer配置类

导入Thymeleaf 模板引擎

  • pom中导入依赖项
  • 添加命名空间
  • 用Thymeleaf 语法替换本地资源部分,如果引用的是网络上的资源,不需要使用这种形式。

Controller配置

1.作用:控制器类,处理由DispatcherServlet分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model返回给对应的View进行展示。

与Controller配合使用的关键字还有GetMapping,PostMapping, RequestMapping等用于获取请求的注解。

WebMvcConfigurer 配置

这一步主要做了以下几点:

  • @Configuration:这个注解修饰的类,说明该类是一个Spring配置类

  • implements WebMvcConfigurer:实现该接口,可以用来扩展WebMvcConfigurer的配置

  • public void addViewControllers(ViewControllerRegistry registry) {}:重写addViewControllers()方法,添加一个视图控制器

  • registry.addViewController("/").setViewName(“index”);:添加视图控制,设置url-pattern,指向视图index。(前缀和后缀在Thymeleaf视图解析器中默认设置)

这里就不详细说了,详情可参考我的这篇博文
WebMvcConfigurer 配置

三、国际化

国际化指的是页面可以实现多语言展示,既可以显示中文,又可以显示英文页面或者其它语言。

注意:实现国际化之前,要保证项目编码使用的是UTF-8,否则可能会出现中文乱码问题。

  • 编写中英文的properties配置文件
  • 在application.yml中设置消息的basename来引用刚刚的配置文件,basename指向国际化文件的真实位置
  • 修改HTML中的文本引用
  • 配置SpringBoot中的区域解析器

这里详细说一下区域解析器的配置

解读:WebMvcAutoConfiguration类中的localeResolver()方法:

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
  if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
    return new FixedLocaleResolver(this.mvcProperties.getLocale());
  }
  AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
  localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
  return localeResolver;
  • 如果我们在配置文件中配置了mvcProperties的属性,则会根据配置文件来配置LocaleResolver对象
  • 如果配置文件没有配置,则返回一个默认的LocaleResolver

因为我们没有在application.yaml中配置关于区域的属性,所以SpringBoot会使用默认的LocaleResolver。

看一下默认的区域解析器是怎么生成的:

AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());

是通过实例化AcceptHeaderLocaleResolver对象,设置默认的区域配置来生成的区域解析器。

打开AcceptHeaderLocaleResolver类看一下:

public class AcceptHeaderLocaleResolver implements LocaleResolver {

这个类实现了LocaleResolver接口,并实现了resolveLocale()方法:

@Override
public Locale resolveLocale(HttpServletRequest request) {
  Locale defaultLocale = getDefaultLocale();
  if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
    return defaultLocale;
  }
  Locale requestLocale = request.getLocale();
  List<Locale> supportedLocales = getSupportedLocales();
  if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
    return requestLocale;
  }
  Locale supportedLocale = findSupportedLocale(request, supportedLocales);
  if (supportedLocale != null) {
    return supportedLocale;
  }
  return (defaultLocale != null ? defaultLocale : requestLocale);
}

所以,我们也可以自定义一个类来实现LocaleResolver这个接口,并重现接口中的方法,这就是我们自定义的区域解析器:

public class MyLocaleResolver implements LocaleResolver {
    /**
     * 解析请求
     *
     * @param request
     * @return
     */
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //获取请求参数
        String lang = request.getParameter("lang");
//        System.out.println("lang:"+lang);
        Locale locale = Locale.getDefault();
        if (!StringUtils.isEmpty(lang)) {
            String[] split = lang.split("_");
            locale = new Locale(split[0], split[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

当我们定义完视图解析器后,需要到MyMvcConfig配置类中将区域解析器注册到IoC容器中,让解析器生效。

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    /**
     * 添加视图控制器
     *
     * @param registry
     */

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        System.out.println("come in ");
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
        registry.addViewController("/main").setViewName("dashboard");
        registry.addViewController("/main.html").setViewName("dashboard");
    }

    /**
     * 添加自定义的区域解析器
     *
     * @return
     */
    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocaleResolver();
    }
}

四、页面登录、注销

登录登出,如果登录成功,页面将跳转到dashboard;

登录不成功,设置一个msg提示消息,并跳转到index页面。

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpSession;

@Controller   //处理http请求
public class LoginController {

    /**
     * 登录验证
     *
     * @param username
     * @param password
     * @param model
     * @param session
     * @return
     */
    @PostMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        Model model,
                        HttpSession session) {
        if ("admin".equals(username) && "123".equals(password)) {
            session.setAttribute("loginUser", username);
            return "redirect:/main.html";
        } else {
            model.addAttribute("msg", "用户名或密码错误");
            return "index";
        }
    }


    /**
     * 注销登录
     *
     * @return
     */
    @GetMapping("/logout")
    public String logout(HttpSession session, Model model) {
        session.invalidate();
        model.addAttribute("msg", "注销成功");
        return "redirect:/index.html";
    }
}

登录成功后,在后台页面的地址栏中显示的仍然是带有请求参数的URL,这样看着就很不和谐。所以这里采用重定向来解决和这个问题,登录成功后重定向到首页。

五、登录拦截器

拦截器在学习SpringMVC时就已经接触过,可以通过拦截器实现对登录的拦截,只有登录成功才可以访问后台页面,否则不能直接访问后台页面。

在这里主要是采用对接口HandlerInterceptor进行实现,查看源码

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}
  • preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
  • postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
  • afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);

本次登录拦截采用实现HandlerInterceptor接口的preHandle方法即可。首先在登录的时候,我们会选择在session域中存储一个属性loginUser,用于拦截器判断拦截的依据:

if ("admin".equals(username) && "123".equals(password)) {
  //登录成功,存储"loginUser"属性
  session.setAttribute("loginUser",username);
  return "redirect:/main";
}

在config包下新建登录拦截器,自定义类实现HandlerInterceptor接口,实现preHandle方法:

public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //登录成功之后,应该有用户的Session
        String loginUser = (String) request.getSession().getAttribute("loginUser");

        if (loginUser == null) {
            request.setAttribute("msg", "没有权限,请先登录");
            request.getRequestDispatcher("/").forward(request, response);
            return false;   //不放行
        }
        return true;   //放行
    }
}

登录拦截是属于WebMvcConfigure接口中的一个方法,需要在视图解析器里面进行重写,把自定义的拦截器注入到IoC容器中。把要放行的资源路径都添加进来,包括静态资源,否则样式等等都会被拦截。

这一步相当于Spring在xml中配置拦截器。

    /**
     * 添加自定义的拦截器LoginHandlerInterceptor
     * 指定要拦截和放行的资源
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor())
                .addPathPatterns("/*")
                .excludePathPatterns("/", "/index.html", "/login", "/css/*", "/img/*", "/js/*", "/emp/*");
    }

六、展示员工列表

1. 首先进行数据库连接

有关mybatis-springboot整合的详细部分,详情可参考我的这篇博客
SpringBoot整合JDBC, Mybatis框架

2. 抽取页面公共部分

这里主要就是采用thymeleaf模板引擎中的替换语法,可支持传参功能

th:replace="~{commons/commons::sidebar(active='main')}"

3. 员工列表展示

在controller包下新建一个控制器EmployeeController,用来获取员工数据并跳转到list.html页面:

@Controller
public class EmployeeController {

    @Autowired
    private EmployeeMapper employeeMapper;

    List<String> departmentsPermanent = Arrays.asList("部门1","部门2","部门3","部门4","部门5");

    /**
     * 获取所有员工数据,并在model中添加emps属性,将获取到的员工集合放进去
     *
     * @param model
     * @return
     */
    @RequestMapping("/emps")
    public String list(Model model) {
        Collection<Employee> employees = employeeMapper.queryEmps();
        model.addAttribute("emps", employees);
        return "emp/list";
    }
}

七. 增加员工展示

这里主要就两个操作,一个是点击添加员工按钮后,携带相应的数据并跳转到添加页面,然后在添加页面点击提交按钮后,再添加数据保存到数据库中。

    /**
     * 获取"添加员工"页面
     *
     * @return
     */
    @GetMapping("/add")
    public String getAddPage(Model model) {
        //获取所有部门信息
        Collection<Employee> employees = employeeMapper.queryEmps();
        //将部门信息添加到model中
//        model.addAttribute("employees", employees);
        model.addAttribute("departmentsPermanent", departmentsPermanent);
        return "emp/add";
    }

    /**
     * 执行添加员工操作
     *
     * @param employee
     * @return
     */
    @PostMapping("/add")
    public String addMethod(Employee employee) {
        employeeMapper.addEmp(employee);
        return "redirect:/emps";
    }

八. 修改员工信息

这里主要就两个操作,一个是点击修改编辑按钮后,携带相应的数据并跳转到修改页面,然后在修改页面点击提交按钮后,再将修改的数据保存到数据库中。

/**
     * 更新员工信息
     *
     * @param employee
     * @return
     */
    @PostMapping("/update")
    public String updateMethod(Employee employee) {
        employeeMapper.updateEmp(employee);
        return "redirect:/emps";
    }

    /**
     * 通过员工id删除员工
     *
     * @param id
     * @return
     */
    @GetMapping("/delete/{id}")
    public String deleteMethod(@PathVariable("id") Integer id) {
        employeeMapper.deleteEmpById(id);
        return "redirect:/emps";
    }

九. 修改员工信息及404页面

点击删除按钮后,直接调用删除功能,把数据删除即可

    /**
     * 通过员工id删除员工
     *
     * @param id
     * @return
     */
    @GetMapping("/delete/{id}")
    public String deleteMethod(@PathVariable("id") Integer id) {
        employeeMapper.deleteEmpById(id);
        return "redirect:/emps";
    }

添加404页面非常简单,只需要在templates目录下新建error文件夹,在里面添加404.html即可,当前端访问出现404时,会跳转到这个页面。

稍后我会将所有源代码包括sql创建等上传

参考资料:
https://javabook.shiguangping.com/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:微人事是一个前后端分离的人力资源管理系统,项目采用 SpringBoot + Vue 开发。项目打通了前后端,并且提供了非常详尽的文档,从 Spring Boot 接口设计到前端 Vue 的开发思路,作者全部都记录在项目的 wiki 中,是不可多得的 Java 全栈学习资料。引用\[2\]:其实前后端分离本身并不难,后段提供接口,前端做数据展示,关键是这种思想。很多人做惯了前后端不分的开发,在做前后端分离的时候,很容易带进来一些前后端不分时候的开发思路,结果做出来的产品不伦不类,因此松哥这里给大家整理了几个开源的前后端分离项目,帮助大家快速掌握前后端分离开发技术栈。美人鱼 star 数 3499项目地址: https://gitee.com/mumu-osc/NiceFish。引用\[3\]:听名字就知道这是个不错的项目,事实上确实不赖。NiceFish(美人鱼) 是一个系列项目,目标是示范前后端分离的开发模式:前端浏览器、移动端、Electron 环境中的各种开发模式;后端有两个版本:SpringBoot 版本和 SpringCloud 版本,前端有 Angular 、React 以及 Electron 等版本。 针对您的问题,如果您想了解关于SpringBoot前后端分离的项目,可以考虑微人事和NiceFish这两个项目。微人事是一个人力资源管理系统,采用了SpringBoot和Vue进行开发,项目提供了详尽的文档,记录了从Spring Boot接口设计到前端Vue开发的思路,是一个非常有价值的Java全栈学习资料。而NiceFish是一个系列项目,旨在示范前后端分离的开发模式,包括前端浏览器、移动端和Electron环境中的各种开发模式,后端有SpringBoot版本和SpringCloud版本,前端有Angular、React和Electron等版本。这些项目都是开源的,可以帮助您快速掌握前后端分离开发技术栈。 #### 引用[.reference_title] - *1* *2* *3* [七个开源的 Spring Boot 前后端分离项目,一定要收藏!](https://blog.csdn.net/u012702547/article/details/100973824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值