1. pom.xml引入<groupId>org.projectlombok</groupId> 依赖,实体类前加@Data注解就会自动帮忙生成getsetter方法等.
<artifactId>lombok</artifactId>
2. @NoArgsConstructor
@AllArgsConstructor 有参构造和无参构造
3. Controller写一个register方法,service里声明方法,mapper里写sql
4. @Service
public class UserServiceImpl implements UserService {
@Autowired 别忘了Autowired注解
private UserMapper userMapper;
@Override
public User findByUsername(String username) {
User u=userMapper.findByUsername(username);
return u;
}别忘了Autowired注解别忘了Autowired注解别忘了Autowired注解别忘了Autowired注解别忘了Autowired注解别忘了Autowired注解
5. @Validated
public Result register(@Pattern(regexp = "^\\S{5,16}$") String username,@Pattern(regexp = "^\\S{5,16}$") String password) 正则表达式对用户名和密码进行位数限制,要引入依赖。
6. 异常处理,全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e){
e.printStackTrace();
return Result.error(StringUtils.hasLength(e.getMessage())?e.getMessage():"操作失败");
}
}
7.自定义注解state
(1)自定义校验数据的类StateValidation
(2)实现ConstraintValidator接口
(3)在需要校验的地方使用自定义注解
8. 分页查询的ServiceImpl
@Override public PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) { //创建pagebean对象 PageBean<Article> pb=new PageBean<>(); //开启分页查询 Pagehelper PageHelper.startPage(pageNum,pageSize); // 调用mapper Map<String,Object>map =ThreadLocalUtil.get(); Integer userId = (Integer) map.get("id"); List<Article> as= articleMapper.list(userId,categoryId, state); //Page中提供了方法,可以获取PageHelper分页查询后,得到的总记录条数和当前页数据 Page<Article> p= (Page<Article>) as; //把数据填到PageBean对象中 pb.setTotal(p.getTotal()); pb.setItems(p.getResult()); return pb; }
9. 动态sql
在resources里面创建一个包com/itheima/mapper
取一个和上面mapper包中同样的类名
<mapper namespace="com.itheima.mapper.ArticleMapper"> <!--动态sql--> <select id="list" resultType="com.itheima.pojo.Article"> select * from article <where> <if test="categoryId!=null"> category_id=#{categoryId} </if> <if test="state!=null"> and state=#{state} </if> and create_user=#{userId} </where> </select> </mapper>
10. 存文件 文件上传
@PostMapping("/upload") public Result<String> upload(MultipartFile file) throws IOException { //把文件的内容存储到本地磁盘上 String originalFilename = file.getOriginalFilename(); //保证文件的名字是唯一的,防止文件覆盖 String filename= UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf(".")); file.transferTo(new File("C:\\Users\\zuzeyu\\Desktop\\Files\\"+filename)); return Result.success("url访问地址..."); }
11.AliOssUtil
package com.itheima.utils; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.PutObjectResult; import java.io.FileInputStream; import java.io.InputStream; public class AliOssUtil { // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com"; // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 //EnvironCmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); private static final String ACESS_KEY_ID="LTAI5tCsYKHsajyBWiqioUQg"; private static final String ACCESS_KEY_SECRET="KA63MwbHkK2joock11czl0v11dQrdq"; // 填写Bucket名称,例如examplebucket。 private static final String BUCKET_NAME = "big-eventzz3"; public static String uploadFile(String objectName, InputStream in) throws Exception { // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。 // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。 // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACESS_KEY_ID, ACCESS_KEY_SECRET); String url=""; try { // 创建PutObjectRequest对象。 PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, in); // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。 // ObjectMetadata metadata = new ObjectMetadata(); // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); // metadata.setObjectAcl(CannedAccessControlList.Private); // putObjectRequest.setMetadata(metadata); // 上传文件。 PutObjectResult result = ossClient.putObject(putObjectRequest); url ="https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+objectName; } 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(); } } return url; } }
12对日期格式化 可以在属性上加注解@JasonFormat(pattern="yyyy-MM-dd HH:mm:ss")
还有一种重写extendMessageConverters创建一个消息转换器
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { log.info("扩展消息转换器........"); //自己创建一个消息转换器对象 MappingJackson2HttpMessageConverter converter =new MappingJackson2HttpMessageConverter(); //需要给消息转换器设置一个对象转换器,对象转换器可以将JAVA对象序列化为json数据 converter.setObjectMapper(new JacksonObjectMapper()); //将自己的转换器加入容器中 converters.add(0,converter); }
13.分页查询 用到了PageHelper
/* * 分页查询 * */ @Override public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) { //开始分页查询 PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize()); Page<Employee> page=employeeMapper.pageQuery(employeePageQueryDTO); long total = page.getTotal(); List<Employee> records = page.getResult(); return new PageResult(total,records); }
14.路径传参要用注解@PathVariable,像这样
@GetMapping("/{id}") public Result<Employee> getById (@PathVariable long id){ return null; }
15.公共字段自动填充 用到了AOP ,反射
@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){ //为四个公共字段赋值 try { Method 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){ //为两个公共字段赋值 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(); } } } }