免费ppt模板网站下载,wordpress评论提交特效,企业文档管理wordpress,网络营销推广方法和工具1、DTO类
DTO#xff08;Data Transfer Object#xff09;#xff1a;数据传输对象#xff0c;Service 或 Manager 向外传输的对象。 详见阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
当前端提交的数据和实体类中对应的属性差别比较大时#xff0c;建议使用…1、DTO类
DTOData Transfer Object数据传输对象Service 或 Manager 向外传输的对象。 详见阿里巴巴Java开发手册中的DO、DTO、BO、AO、VO、POJO定义
当前端提交的数据和实体类中对应的属性差别比较大时建议使用DTO来封装数据。 进入sky-pojo模块在com.sky.dto包下已定义EmployeeDTO
package com.sky.dto;import lombok.Data;import java.io.Serializable;Data
public class EmployeeDTO implements Serializable {private Long id;private String username;private String name;private String phone;private String sex;private String idNumber;}.
2、全局异常处理器
跟异常处理相关的只有注解ExceptionHandler。 详见Spring Boot全局异常处理器原理及使用详解
为什么使用全局异常处理器
不用强制写try-catch由全局异常处理器统一捕获处理。自定义异常只能用全局异常来捕获。不能直接返回给客户端客户端是看不懂的需要接入全局异常处理器JSR303规范的Validator参数校验器参数校验不通过会抛异常是无法使用try-catch语句直接捕获只能使用全局异常处理器。
进入到sky-server模块com.sky.hander包下GlobalExceptionHandler.java添加方法
package com.sky.handler;import com.sky.constant.MessageConstant;
import com.sky.exception.BaseException;
import com.sky.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常处理器处理项目中抛出的业务异常*/
RestControllerAdvice
Slf4j
public class GlobalExceptionHandler {/*** 捕获业务异常* param ex* return*/ExceptionHandlerpublic Result exceptionHandler(BaseException ex){log.error(异常信息{}, ex.getMessage());return Result.error(ex.getMessage());}/*** 处理SQL异常* param ex* return*/ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException ex){//Duplicate entry zhangsan for key employee.idx_usernameString message ex.getMessage();if(message.contains(Duplicate entry)){String[] split message.split( );String username split[2];String msg username MessageConstant.ALREADY_EXISTS;return Result.error(msg);}else{return Result.error(MessageConstant.UNKNOWN_ERROR);}}
}
.
3、jwt令牌校验的拦截器
JWT一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息即传递Token以便于从资源服务器获取资源特别适用于分布式站点的单点登录(SSO)场景跨域认证。 详见ylb-知识点8-jwt 和 关于jwt介绍和代码分析
在sky-server模块com.sky.interceptor包下创建JwtTokenAdminInterceptor和JwtTokenUserInterceptor 步骤
1、判断当前拦截到的是Controller的方法还是其他资源!(handler instanceof HandlerMethod)2、从请求头中获取令牌3、校验令牌
package com.sky.interceptor;import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** jwt令牌校验的拦截器*/
Component
Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** param request* param response* param handler* return* throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法直接放行return true;}//1、从请求头中获取令牌String token request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try {log.info(jwt校验:{}, token);Claims claims JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info(当前员工id, empId);BaseContext.setCurrentId(empId);//3、通过放行return true;} catch (Exception ex) {//4、不通过响应401状态码response.setStatus(401);return false;}}
}
package com.sky.interceptor;import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** jwt令牌校验的拦截器*/
Component
Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** param request* param response* param handler* return* throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法直接放行return true;}//1、从请求头中获取令牌String token request.getHeader(jwtProperties.getUserTokenName());//2、校验令牌try {log.info(jwt校验:{}, token);Claims claims JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);Long userId Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());log.info(当前用户的id, userId);BaseContext.setCurrentId(userId);//3、通过放行return true;} catch (Exception ex) {//4、不通过响应401状态码response.setStatus(401);return false;}}
}
4、ThreadLocal
ThreadLocal 并不是一个Thread而是Thread的局部变量。 ThreadLocal为每个线程提供单独一份存储空间具有线程隔离的效果只有在线程内才能获取到对应的值线程外则不能访问。
常用方法
public void set(T value) 设置当前线程的线程局部变量的值public T get() 返回当前线程所对应的线程局部变量的值public void remove() 移除当前线程的线程局部变量 详见史上最全ThreadLocal 详解一
在sky-common模块com.sky.context包下创建ThreadLocal 操作的工具类BaseContext
package com.sky.context;public class BaseContext {public static ThreadLocalLong threadLocal new ThreadLocal();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}}使用ThreadLocal 操作的工具类 ①在拦截器中解析出当前登录员工id并放入线程局部变量中 ②在Service中获取线程局部变量中的值 .
5、分页插件 PageHelper
mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。
pagehelper 的使用使用的时候只需在查询list前调用 startPage 设置分页信息即可使用分页功能。 详见PageHelper 分页插件使用总结 /*** 分页查询** param employeePageQueryDTO* return*/public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {// select * from employee limit 0,10//开始分页查询PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());PageEmployee page employeeMapper.pageQuery(employeePageQueryDTO);//后续定义long total page.getTotal();ListEmployee records page.getResult();return new PageResult(total, records);}6、JSON的时间字段
前端响应的JSON时间字段出现问题非正常时间格式是一串数字 解决办法在WebMvcConfiguration中扩展SpringMVC的消息转换器统一对日期类型进行格式处理。 /*** 扩展Spring MVC框架的消息转化器* param converters*/protected void extendMessageConverters(ListHttpMessageConverter? converters) {log.info(扩展消息转换器...);//创建一个消息转换器对象MappingJackson2HttpMessageConverter converter new MappingJackson2HttpMessageConverter();//需要为消息转换器设置一个对象转换器对象转换器可以将Java对象序列化为json数据converter.setObjectMapper(new JacksonObjectMapper());//将自己的消息转化器加入容器中converters.add(0,converter);}其中时间格式定义在sky-common模块中com.sky.json包下JacksonObjectMapper添加字符串常量
package com.sky.json;public class JacksonObjectMapper extends ObjectMapper {//.......// 时间格式定义public static final String DEFAULT_DATE_TIME_FORMAT yyyy-MM-dd HH:mm;//.......}
}7、请求方式
HTTP常见的请求方式----GET,POST,PUT,DELETE
get可以理解 为 取 的意思对应select操作 用来获取数据的只是用来查询数据不对服务器的数据做任何的修改新增删除等操作。post 可以理解 为 贴 的意思对应update操作 数据发送到服务器以创建或更新资源侧重于更新数据。put可以理解为 放 的意思对应insert操作 数据发送到服务器以创建或更新资源侧重于创建数据delete字面意思删除即删除数据对应delete操作 用来删除指定的资源它会删除URI给出的目标资源的所有当前内容 详见HTTP的8种请求方式及常用请求方式的解析 .
8、公共字段自动填充
公共字段
使用AOP切面编程实现功能增强来完成公共字段自动填充功能 实现步骤
1). 自定义注解 AutoFill用于标识需要进行公共字段自动填充的方法
2). 自定义切面类 AutoFillAspect统一拦截加入了 AutoFill 注解的方法通过反射为公共字段赋值
3). 在 Mapper 的方法上加入 AutoFill 注解
1、自定义注解 AutoFill
在sky-server模块com.sky.annotation包下创建自定义注解AutoFill
package com.sky.annotation;import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解用于标识某个方法需要进行功能字段自动填充处理*/
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface AutoFill {//数据库操作类型UPDATE INSERTOperationType value();
}
其中OperationType已在sky-common模块中定义
package com.sky.enumeration;/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT
}2、自定义切面 AutoFillAspect
在sky-server模块com.sky.aspect包下创建切面 类AutoFillAspect
package com.sky.aspect;import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;/*** 自定义切面实现公共字段自动填充处理逻辑*/
Aspect
Component
Slf4j
public class AutoFillAspect {/*** 切入点*/Pointcut(execution(* com.sky.mapper.*.*(..)) annotation(com.sky.annotation.AutoFill))public void autoFillPointCut(){}/*** 前置通知在通知中进行公共字段的赋值*/Before(autoFillPointCut())public void autoFill(JoinPoint joinPoint){log.info(开始进行公共字段自动填充...);//获取到当前被拦截的方法上的数据库操作类型MethodSignature signature (MethodSignature) joinPoint.getSignature();//获得方法签名对象AutoFill autoFill signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象OperationType operationType autoFill.value();//获得数据库操作类型//获取到当前被拦截的方法的参数--实体对象Object[] args joinPoint.getArgs();if(args null || args.length 0){return;}// 实体对象Object entity args[0];//准备赋值的数据LocalDateTime now LocalDateTime.now();Long currentId BaseContext.getCurrentId();//根据当前不同的操作类型为对应的属性通过反射来赋值if(operationType OperationType.INSERT){//为4个公共字段赋值// 当前执行的是insert操作try {// 获得set方法对象 --- MethodMethod setCreateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setCreateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射调用目标对象的方法为对象属性赋值setCreateTime.invoke(entity,now);setCreateUser.invoke(entity,currentId);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}}else if(operationType OperationType.UPDATE){//为2个公共字段赋值// 当前执行的是update操作try {Method setUpdateTime entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射为对象属性赋值setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}}}}
3、在Mapper接口的方法上加入 AutoFill 注解
以CategoryMapper为例分别在新增和修改方法添加AutoFill()注解也需要EmployeeMapper做相同操作。
package com.sky.mapper;Mapper
public interface CategoryMapper {/*** 插入数据* param category*/Insert(insert into category(type, name, sort, status, create_time, update_time, create_user, update_user) VALUES (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}))AutoFill(value OperationType.INSERT)void insert(Category category);/*** 根据id修改分类* param category*/AutoFill(value OperationType.UPDATE)void update(Category category);}同时将业务层为公共字段赋值的代码注释掉。 1). 将员工管理的新增和编辑方法中的公共字段赋值的代码注释。 2). 将菜品分类管理的新增和修改方法中的公共字段赋值的代码注释。 .
9、文件上传 – 阿里云的OSS服务进行文件存储 实现步骤
1). 定义OSS相关配置2). 读取OSS配置3). 生成OSS工具类对象4). 定义文件上传接口
1). 定义OSS相关配置
在sky-server模块 application-dev.yml中
sky:alioss:endpoint: oss-cn-hangzhou.aliyuncs.comaccess-key-id: LTAI5tPeFLzsPPT8gG3LPW64access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7bucket-name: sky-take-outapplication.yml中
spring:profiles:active: dev #设置环境
sky:alioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: ${sky.alioss.access-key-secret}bucket-name: ${sky.alioss.bucket-name}2). 读取OSS配置
在sky-common模块中com.sky.properties包下已定义AliOssProperties.java
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;Component
ConfigurationProperties(prefix sky.alioss)
Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}3). 生成OSS工具类对象
在sky-server模块com.sky.config包下定义OSS工具类OssConfiguration.java
package com.sky.config;import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置类用于创建AliOssUtil对象*/
Configuration
Slf4j
public class OssConfiguration {BeanConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info(开始创建阿里云文件上传工具类对象{},aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}其中AliOssUtil.java已在sky-common模块中定义
package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;Data
AllArgsConstructor
Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** param bytes* param objectName* return*/public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println(Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.);System.out.println(Error Message: oe.getErrorMessage());System.out.println(Error Code: oe.getErrorCode());System.out.println(Request ID: oe.getRequestId());System.out.println(Host ID: oe.getHostId());} catch (ClientException ce) {System.out.println(Caught an ClientException, which means the client encountered a serious internal problem while trying to communicate with OSS, such as not being able to access the network.);System.out.println(Error Message: ce.getMessage());} finally {if (ossClient ! null) {ossClient.shutdown();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder new StringBuilder(https://);stringBuilder.append(bucketName).append(.).append(endpoint).append(/).append(objectName);log.info(文件上传到:{}, stringBuilder.toString());return stringBuilder.toString();}
}4). 定义文件上传接口 在sky-server模块com.sky.controller.admin包下定义接口CommonController
package com.sky.controller.admin;import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
RestController
RequestMapping(/admin/common)
Api(tags 通用接口)
Slf4j
public class CommonController {Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* param file* return*/PostMapping(/upload)ApiOperation(文件上传)public ResultString upload(MultipartFile file){log.info(文件上传{},file);try {//原始文件名String originalFilename file.getOriginalFilename();//截取原始文件名的后缀 dfdfdf.pngString extension originalFilename.substring(originalFilename.lastIndexOf(.));//构造新文件名称String objectName UUID.randomUUID().toString() extension;//文件的请求路径String filePath aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.error(文件上传失败{}, e);}return Result.error(MessageConstant.UPLOAD_FAILED);}
}.
10、接口分组展示
Swagger里设置两个docket对象
在WebMvcConfiguration.java中分别扫描com.sky.controller.admin和com.sky.controller.user这两个包。 //...Beanpublic Docket docket1(){log.info(准备生成接口文档...);ApiInfo apiInfo new ApiInfoBuilder().title(苍穹外卖项目接口文档).version(2.0).description(苍穹外卖项目接口文档).build();Docket docket new Docket(DocumentationType.SWAGGER_2).groupName(管理端接口).apiInfo(apiInfo).select()//指定生成接口需要扫描的包.apis(RequestHandlerSelectors.basePackage(com.sky.controller.admin)).paths(PathSelectors.any()).build();return docket;}Beanpublic Docket docket2(){log.info(准备生成接口文档...);ApiInfo apiInfo new ApiInfoBuilder().title(苍穹外卖项目接口文档).version(2.0).description(苍穹外卖项目接口文档).build();Docket docket new Docket(DocumentationType.SWAGGER_2).groupName(用户端接口).apiInfo(apiInfo).select()//指定生成接口需要扫描的包.apis(RequestHandlerSelectors.basePackage(com.sky.controller.user)).paths(PathSelectors.any()).build();return docket;}//...