SpringBoot实践项目

news/2024/10/29 1:16:26/

开发工具

插件:

Maven Helper
Free Mybatis Plugin

API工具

PostMan

数据库

mysql

可视化工具

Navicat

JDK

version 1.8

IDE

IDEA 2023.1

技术栈

SpringBoot 2.2.1.RELEASE
Mybatis 3.4.6
Maven 3.6.0
Log4j2 2.12.1

开发步骤

新建SpringBoot项目

直接使用IDEA 选择Spring Initializr 然后选择 Spring Web 就能生成最基本的 springBoot项目

生成逆向文件,这个主要是根据数据库自动生成pojo实体

步骤如下:

  1. 增加依赖 mybatis,mysql-connector (这个其实是数据库配置)
  2. 增加插件 mybatis-generator
  3. 引入配置文件 generatorConfig.xml

引入mybatis

application.properties配置文件增加mybatis配置

    spring.datasource.name=imooc_mall_datasourcespring.datasource.url=jdbc:mysql://127.0.0.1:3306/imooc_mall? serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghaispring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.username=rootspring.datasource.password=123456# 配置mapper文件映射mybatis.mapper-locations=classpath:mappers/*.xml

将日志替换为log4j2

  1. 首先pom.xml中去除掉原本的log日志,同时引入log4j2依赖
 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency>
  1. resource下新建log4j2.xml配置文件,此处注意配置的日志级别,容易出现不打印sql日志问题

  2. 使用AOP打印请求URL及请求参数

分模块开发

用户模块

这里有几个重要点值得注意
统一接口返回{
a. 成功无数据返回
b. 成功有数据返回
c. 处理失败返回 便于管理,定义失败枚举类
d. 异常处理返回 统一返回,使用异常处理器获取异常后处理为统一返回码(这一块重点关注,使用了SpringBoot注解) => 抛出的异常直接转换为ApiRestResponse的json串
}
备注:使用统一接口返回类时,返回对象使用报错:No converter found for return value of type: class com.imooc.mall.common.ApiRestResponse" ,分析后时缺少部分字段的get/set方法

这里给出异常处理的代码,有两个重要的注解
@RestControllerAdvice 表明全局拦截异常
@ExceptionHandler表明处理的异常类型

@RestControllerAdvice
public class GlobalExceptionHandle {private final Logger log = LoggerFactory.getLogger(GlobalExceptionHandle.class);@ExceptionHandler(Exception.class)public Object handleException(Exception ex){log.error("Default Exception: ", ex);return ApiRestResponse.error(BusinessExceptionEnum.SYSTEM_ERROR);}@ExceptionHandler(BusinessException.class)public ApiRestResponse handleBusinessException(BusinessException ex){log.error("Business Exception: ", ex);return ApiRestResponse.error(ex.getCode(),ex.getMessage());}
}

用户注册

    此处使用MD5加密密码,引入异常处理器处理异常为统一返回

用户登录

    登录状态保存利用session服务端把用户信息保存到session

用户登出

    登录状态删除利用session服务端把用户信息从session删除

用户个人信息修改

    利用session获取用户修改数据

该模块重难点,常见错误

  1. 重难点:统一响应对象(ApiRestResponse),登录状态保持(session),统一异常处理(ExceptionHandler)
  2. 常见错误:响应对象不规范,异常不统一处理

商品目录管理

这个模块主要引入了几个重要的技术点
使用@Valid增加参数校验,然后在异常统一处理中针对校验异常做处理[ ex.getBindingResult() 获取异常绑定信息 ]

商品目录新增

商品目录删除

商品目录查询后端

商品目录查询前端

@Valid注解使用已经挺熟悉了,就不加赘述,此处主要说明一下,参数校验不通过之后的异常处理怎么弄
从异常中获取办绑定的返回结果,然后取出message作为返回信息,利用统一接口返回做处理

@ExceptionHandler(MethodArgumentNotValidException.class)public ApiRestResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {// 把异常处理为对外暴露的提示log.error("MethodArgumentNotValid Exception: ", ex);return handleBindingResult(ex.getBindingResult());}/*** 将异常转换为标准接口返回** @param bindingResult* @return*/private ApiRestResponse handleBindingResult(BindingResult bindingResult) {List<String> list = new ArrayList<>();if (bindingResult.hasErrors()) {List<ObjectError> allErrors = bindingResult.getAllErrors();for (ObjectError error : allErrors) {String message = error.getDefaultMessage();list.add(message);}}if (list == null) {return ApiRestResponse.error(BusinessExceptionEnum.PARAM_ERROR);}return ApiRestResponse.error(BusinessExceptionEnum.PARAM_ERROR.getCode(), list.toString());}
  1. 引入过滤器,统一拦截需要管理员权限的接口url,然后做鉴权处理

引入过滤器实现重点是声明一个 过滤器实现Filter 接口,然后重写其中的处理方法
然后配置过滤器的配置类
需要注意的点是:过滤后的返回使用out回写,另外就是过滤器的配置类
另外就是 拦截器与过滤器的区别与联系
还有注意点就是过滤器的注册会在springContext容器初始化前,所以如果配置过滤器时可能会导致依赖注入失败问题,需要在配置文件中使用bean注入。

package com.imooc.mall.config;import com.imooc.mall.filter.AdminFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 描述:     Admin过滤器的配置*/
@Configuration
public class AdminFilterConfig {@Beanpublic AdminFilter adminFilter() {return new AdminFilter();}@Bean(name = "adminFilterConf")public FilterRegistrationBean adminFilterConfig() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(adminFilter());filterRegistrationBean.addUrlPatterns("/admin/category/*");filterRegistrationBean.addUrlPatterns("/admin/product/*");filterRegistrationBean.addUrlPatterns("/admin/order/*");filterRegistrationBean.setName("adminFilterConf");return filterRegistrationBean;}
}
package com.imooc.mall.filter;import com.imooc.mall.common.ApiRestResponse;
import com.imooc.mall.common.Constant;
import com.imooc.mall.exception.BusinessExceptionEnum;
import com.imooc.mall.model.pojo.User;
import com.imooc.mall.service.UserService;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;/*** todo** @author wangwei* @version 1.0.0* @since 2023-04-03*/public class AdminFilter implements Filter {@AutowiredUserService userService;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;filterChain.doFilter(servletRequest, servletResponse);HttpSession session = request.getSession();User currentUser = (User) session.getAttribute(Constant.MAIL_USER);if (currentUser == null) {PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();out.write("{\n"+ "    \"status\": 10007,\n"+ "    \"msg\": \"NEED_LOGIN\",\n"+ "    \"data\": null\n"+ "}");out.flush();out.close();return;}// 校验是否是管理员if (!userService.checkAdminRole(currentUser)) {PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) servletResponse).getWriter();out.write("{\n"+ "    \"status\": 10009,\n"+ "    \"msg\": \"NEED_ADMIN\",\n"+ "    \"data\": null\n"+ "}");out.flush();out.close();return;}filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}
}

上述是过滤器的实现,接下来也分析一下拦截器的实现
主要有以下步骤
① 实现拦截器继

package com.imooc.mall.aop;import com.imooc.mall.common.Constant;
import com.imooc.mall.model.pojo.User;import com.imooc.mall.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;/*** todo** @author wangwei* @version 1.0.0* @since 2023-04-04*/
public class AdminInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();User user = (User) session.getAttribute(Constant.MAIL_USER);if (user == null) {System.out.println("这里拦截器拦截住需要用户校验的请求");PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) response).getWriter();out.write("{\n"+ "    \"status\": 10007,\n"+ "    \"msg\": \"NEED_LOGIN\",\n"+ "    \"data\": null\n"+ "}");out.flush();out.close();return false;}// 校验是否是管理员if (!userService.checkAdminRole(user)) {PrintWriter out = new HttpServletResponseWrapper((HttpServletResponse) response).getWriter();out.write("{\n"+ "    \"status\": 10009,\n"+ "    \"msg\": \"NEED_ADMIN\",\n"+ "    \"data\": null\n"+ "}");out.flush();out.close();return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

② 拦截器配置文件

package com.imooc.mall.config;import com.imooc.mall.aop.AdminInterceptor;import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {// 静态资源映射@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/")  // 映射swagger2.addResourceLocations("file:/workspaces/images/");  // 映射本地静态资源}@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {return builder.build();}/***  IOC容器注入拦截器* @return*/@Beanpublic AdminInterceptor adminInterceptor() {return new AdminInterceptor();}/*** 注册拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(adminInterceptor()).addPathPatterns("/admin/**");WebMvcConfigurer.super.addInterceptors(registry);}
}

注意点是:依赖注入的时候需要关注,配置的拦截地址需要注意

  1. 引入swagger文档
    引入swagger主要有以下几个步骤:
    ①pom.xml依赖导入:
        <!-- 生成API文档--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>

②引入配置文件
WebMallMvcConfig

package com.imooc.mall.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 配置地址映射** @author wangwei* @version 1.0.0* @since 2023-04-03*/@Configuration
public class WebMallMvcConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}

SpringFoxConfig

package com.imooc.mall.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;@Configuration
public class SpringFoxConfig {//访问http://localhost:8083/swagger-ui.html可以看到API文档@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("生鲜商城").description("").termsOfServiceUrl("").build();}
}

③ 最后在需要描述的API上增加注解 @ApiOperation(“后台添加目录”) 启动类增加注解 @EnableSwagger2

  1. 整合Redis自动缓存查询结果
    ① pom.xml增加redis缓存依赖
        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>

② properties配置redis配置

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=

③ 增加缓存配置

package com.imooc.mall.config;import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;import java.time.Duration;/*** 描述:     缓存的配置类*/
@Configuration
@EnableCaching
public class CachingConfig {@Beanpublic RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {RedisCacheWriter redisCacheWriter = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(1110));RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter,cacheConfiguration);return redisCacheManager;}
}

④ 在需要缓存的实现类上加上注解 @Cacheable(value = “listForCustomer”) 启动类增加注解 @Cacheable


http://www.ppmy.cn/news/37940.html

相关文章

原来count(*)是接口性能差的真凶

以下文章来源于苏三说技术 &#xff0c;作者苏三呀 一.前言 最近我在公司优化过几个慢查询接口的性能&#xff0c;总结了一些心得体会拿出来跟大家一起分享一下&#xff0c;希望对你会有所帮助。 我们使用的数据库是Mysql8&#xff0c;使用的存储引擎是Innodb。这次优化除了优…

蓝桥杯带刷题

A::::::::::::::::::小数第n位 题目描述 我们知道&#xff0c;整数做除法时&#xff0c;有时得到有限小数&#xff0c;有时得到无限循环小数。 如果我们把有限小数的末尾加上无限多个 0&#xff0c;它们就有了统一的形式。 本题的任务是&#xff1a;在上面的约定下&#xff…

CISAW-CISDR灾难备份与恢复专业级认证

证书样板&#xff1a; 认证机构 中国网络安全审查技术与认证中心&#xff08;英文缩写为&#xff1a;CCRC,原为中国信息安全认证中心&#xff09;于 2006 年由中央机构编制委员会办公室批准成立&#xff0c;为国家市场监督管理总局直属事业单位。依据《网络安全法》 《网络安…

【Redis】持久化

持久化方式 RDB(Redis Database) 持久化方式&#xff1a;将 Redis 在内存中的数据快照以二进制形式保存到磁盘上&#xff0c;可通过配置不同的保存策略来实现定时备份或者手动触发备份。RDB 持久化方式具有非常高的性能和恢复速度。 AOF(Append Only File) 持久化方式&#xf…

Linux 常见命令

文章目录&#xff1a; 1.ls 11.mv 2.cd 12.netstat 3.pwd 4.touch 5.echo 6.cat 7.vim 8.mkdir 9.rm 10.cp 1.ls 查看当前目录下有哪些目录或者文件 此时这里表示根目录下的root目录下有哪些目录或者文件 2.cd 表示切换到那个目录 几种特…

100天精通Python丨黑科技篇 —— 06、Python 修图(滤镜、灰度、裁剪、视觉处理、图像分割、特征提取)

文章目录一、PIL 常规修图操作1. 读取图片2. 图片缩放3. 图片旋转4. 图片裁剪5. 图片滤镜二、OpenCV 图像处理、视频处理、对象识别三、scikit-image 视觉算法&#xff0c;包括滤波、形态学操作、图像分割、特征提取四、TensorFlow 图像分类、目标检测、图像生成有些小伙伴可能…

Linux系统一键安装最新内核并开启 BBR 脚本

本脚本适用环境 系统支持&#xff1a;CentOS 6&#xff0c;Debian 8&#xff0c;Ubuntu 16 虚拟技术&#xff1a;OpenVZ 以外的&#xff0c;比如 KVM、Xen、VMware 内存要求&#xff1a;≥128M 更新日期&#xff1a;2022 年 5 月 11 日 关于本脚本 1、本脚本已在 蓝易云 上…

PCB生产工艺流程二:图形电镀工艺流程说明

PCB生产工艺流程二&#xff1a;图形电镀工艺流程说明 我们以多层板的工艺流程作为PCB工艺介绍的引线&#xff0c;选择其中的图形电镀工艺进行流程说明&#xff0c;具体分为八部分进行介绍&#xff0c;分类及流程如下&#xff1a; A.内层线路&#xff08;光成像工序&#xff0…