当前位置:   article > 正文

JavaWeb(p135-p155)

JavaWeb(p135-p155)

分页查询

可以利用分页插件PageHelper

1.引入依赖

  1. <dependency>
  2. <groupId>com.github.pagehelper</groupId>
  3. <artifactId>pagehelper-spring-boot-starter</artifactId>
  4. <version>1.4.2</version>
  5. </dependency>

2.EmpMapper

  1. @Mapper
  2. public interface EmpMapper {
  3. //获取当前页的结果列表
  4. public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
  5. }

3. EmpServiceImpl

  1. @Slf4j
  2. @Service
  3. public class EmpServiceImpl implements EmpService {
  4. @Autowired
  5. private EmpMapper empMapper;
  6. @Override
  7. public PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
  8. //设置分页参数
  9. PageHelper.startPage(page, pageSize);
  10. //执行条件分页查询
  11. List<Emp> empList = empMapper.list(name, gender, begin, end);
  12. //获取查询结果
  13. Page<Emp> p = (Page<Emp>) empList;
  14. //封装PageBean
  15. PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
  16. return pageBean;
  17. }
  18. }
  1. @Slf4j
  2. @RestController
  3. @RequestMapping("/emps")
  4. public class EmpController {
  5. @Autowired
  6. private EmpService empService;
  7. //条件分页查询
  8. @GetMapping
  9. public Result page(@RequestParam(defaultValue = "1") Integer page,
  10. @RequestParam(defaultValue = "10") Integer pageSize,
  11. String name, Short gender,
  12. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
  13. @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
  14. //记录日志
  15. log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize,name, gender, begin, end);
  16. //调用业务层分页查询功能
  17. PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);
  18. //响应
  19. return Result.success(pageBean);
  20. }
  21. }

阿里云上传

1 引入依赖

  1. <dependency>
  2. <groupId>com.aliyun.oss</groupId>
  3. <artifactId>aliyun-sdk-oss</artifactId>
  4. <version>3.15.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>javax.xml.bind</groupId>
  8. <artifactId>jaxb-api</artifactId>
  9. <version>2.3.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>javax.activation</groupId>
  13. <artifactId>activation</artifactId>
  14. <version>1.1.1</version>
  15. </dependency>
  16. <!-- no more than 2.3.3-->
  17. <dependency>
  18. <groupId>org.glassfish.jaxb</groupId>
  19. <artifactId>jaxb-runtime</artifactId>
  20. <version>2.3.3</version>
  21. </dependency>

 2 引入阿里云oss上传文件工具类

  1. import com.aliyun.oss.OSS;
  2. import com.aliyun.oss.OSSClientBuilder;
  3. import org.springframework.stereotype.Component;
  4. import org.springframework.web.multipart.MultipartFile;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.util.UUID;
  8. @Component
  9. public class AliOSSUtils {
  10. private String endpoint = "https://oss-cn-shanghai.aliyuncs.com";
  11. private String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";
  12. private String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";
  13. private String bucketName = "web-framework01";
  14. /**
  15. * 实现上传图片到OSS
  16. */
  17. public String upload(MultipartFile multipartFile) throws IOException {
  18. // 获取上传的文件的输入流
  19. InputStream inputStream = multipartFile.getInputStream();
  20. // 避免文件覆盖
  21. String originalFilename = multipartFile.getOriginalFilename();
  22. String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
  23. //上传文件到 OSS
  24. OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
  25. ossClient.putObject(bucketName, fileName, inputStream);
  26. //文件访问路径
  27. String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
  28. // 关闭ossClient
  29. ossClient.shutdown();
  30. return url;// 把上传到oss的路径返回
  31. }
  32. }

 3 controller代码

  1. import com.itheima.pojo.Result;
  2. import com.itheima.utils.AliOSSUtils;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.PostMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import org.springframework.web.multipart.MultipartFile;
  8. import java.io.IOException;
  9. @Slf4j
  10. @RestController
  11. public class UploadController {
  12. @Autowired
  13. private AliOSSUtils aliOSSUtils;
  14. @PostMapping("/upload")
  15. public Result upload(MultipartFile image) throws IOException {
  16. //调用阿里云OSS工具类,将上传上来的文件存入阿里云
  17. String url = aliOSSUtils.upload(image);
  18. //将图片上传完成后的url返回,用于浏览器回显展示
  19. return Result.success(url);
  20. }
  21. }

配置文件

可以将阿里云里的配置信息放到配置文件里面 定义一个配置类,加入注解component让他自动注入上面的类中,加一个configurationproperties能够解析出yml中的阿里云,Data是要在aliossutil中引入get函数得到文件中的内容,同时还要引入一个依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
 

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "aliyun.oss")
  4. public class AliOSSProperties {
  5. private String endpoint;
  6. private String accessKeyId;
  7. private String accessKeySecret;
  8. private String bucketName;
  9. }

登录认证

令牌技术

jwt:json web token由三个部分组成,header记录令牌类型,签名算法,payload携带自定义信息,signature加入指定秘钥

要使用jwt令牌要先引入依赖<!-- JWT依赖-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

jwt工具类:

  1. public class JwtUtils {
  2. private static String signKey = "itheima";//签名密钥
  3. private static Long expire = 43200000L; //有效时间
  4. /**
  5. * 生成JWT令牌
  6. * @param claims JWT第二部分负载 payload 中存储的内容
  7. * @return
  8. */
  9. public static String generateJwt(Map<String, Object> claims){
  10. String jwt = Jwts.builder()
  11. .addClaims(claims)//自定义信息(有效载荷)
  12. .signWith(SignatureAlgorithm.HS256, signKey)//签名算法(头部)
  13. .setExpiration(new Date(System.currentTimeMillis() + expire))//过期时间
  14. .compact();
  15. return jwt;
  16. }
  17. /**
  18. * 解析JWT令牌
  19. * @param jwt JWT令牌
  20. * @return JWT第二部分负载 payload 中存储的内容
  21. */
  22. public static Claims parseJWT(String jwt){
  23. Claims claims = Jwts.parser()
  24. .setSigningKey(signKey)//指定签名密钥
  25. .parseClaimsJws(jwt)//指定令牌Token
  26. .getBody();
  27. return claims;
  28. }
  29. }

 Logincontroller:注入业务层的对象

  1. @Slf4j
  2. @RestController
  3. public class LoginController {
  4. @Autowired
  5. private EmpService empService;
  6. @PostMapping("/login")
  7. public Result login(@RequestBody Emp emp){
  8. log.info("员工登录: {}", emp);
  9. Emp e = empService.login(emp);
  10. //登录成功,生成令牌,下发令牌
  11. if (e != null){
  12. Map<String, Object> claims = new HashMap<>();
  13. claims.put("id", e.getId());
  14. claims.put("name", e.getName());
  15. claims.put("username", e.getUsername());
  16. String jwt = JwtUtils.generateJwt(claims); //jwt包含了当前登录的员工信息
  17. return Result.success(jwt);
  18. }
  19. //登录失败, 返回错误信息
  20. return Result.error("用户名或密码错误");
  21. }
  22. }

过滤器Filter

第一步:定义过滤器,定义一个类实现Filter接口,并重写方法

第二步:配置过滤器,Filter类加入@WebFilter注解,配置拦截资源的路径,写在其中的urlPatterns中,引导类上加@ServletComponentScan注解,开启Servlet组件支持

过滤器操作:

  1. @Slf4j
  2. //@WebFilter(urlPatterns = "/*")
  3. public class LoginCheckFilter implements Filter {
  4. @Override
  5. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  6. HttpServletRequest req = (HttpServletRequest) request;
  7. HttpServletResponse resp = (HttpServletResponse) response;
  8. //1.获取请求url。
  9. String url = req.getRequestURL().toString();
  10. log.info("请求的url: {}",url);
  11. //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
  12. if(url.contains("login")){
  13. log.info("登录操作, 放行...");
  14. chain.doFilter(request,response);
  15. return;
  16. }
  17. //3.获取请求头中的令牌(token)。
  18. String jwt = req.getHeader("token");
  19. //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
  20. if(!StringUtils.hasLength(jwt)){
  21. log.info("请求头token为空,返回未登录的信息");
  22. Result error = Result.error("NOT_LOGIN");
  23. //手动转换 对象--json --------> 阿里巴巴fastJSON
  24. String notLogin = JSONObject.toJSONString(error);
  25. resp.getWriter().write(notLogin);
  26. return;
  27. }
  28. //5.解析token,如果解析失败,返回错误结果(未登录)。
  29. try {
  30. JwtUtils.parseJWT(jwt);
  31. } catch (Exception e) {//jwt解析失败
  32. e.printStackTrace();
  33. log.info("解析令牌失败, 返回未登录错误信息");
  34. Result error = Result.error("NOT_LOGIN");
  35. //手动转换 对象--json --------> 阿里巴巴fastJSON
  36. String notLogin = JSONObject.toJSONString(error);
  37. resp.getWriter().write(notLogin);
  38. return;
  39. }
  40. //6.放行。
  41. log.info("令牌合法, 放行");
  42. chain.doFilter(request, response);
  43. }
  44. }

拦截器Interceptor

配置类 需要加一个配置类注解

  1. @Configuration //配置类
  2. public class WebConfig implements WebMvcConfigurer {
  3. @Autowired
  4. private LoginCheckInterceptor loginCheckInterceptor;
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
  8. }
  9. }

 设置拦截器:

  1. @Slf4j
  2. @Component
  3. public class LoginCheckInterceptor implements HandlerInterceptor {
  4. @Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
  5. public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
  6. //1.获取请求url。
  7. String url = req.getRequestURL().toString();
  8. log.info("请求的url: {}",url);
  9. //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
  10. if(url.contains("login")){
  11. log.info("登录操作, 放行...");
  12. return true;
  13. }
  14. //3.获取请求头中的令牌(token)。
  15. String jwt = req.getHeader("token");
  16. //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
  17. if(!StringUtils.hasLength(jwt)){
  18. log.info("请求头token为空,返回未登录的信息");
  19. Result error = Result.error("NOT_LOGIN");
  20. //手动转换 对象--json --------> 阿里巴巴fastJSON
  21. String notLogin = JSONObject.toJSONString(error);
  22. resp.getWriter().write(notLogin);
  23. return false;
  24. }
  25. //5.解析token,如果解析失败,返回错误结果(未登录)。
  26. try {
  27. JwtUtils.parseJWT(jwt);
  28. } catch (Exception e) {//jwt解析失败
  29. e.printStackTrace();
  30. log.info("解析令牌失败, 返回未登录错误信息");
  31. Result error = Result.error("NOT_LOGIN");
  32. //手动转换 对象--json --------> 阿里巴巴fastJSON
  33. String notLogin = JSONObject.toJSONString(error);
  34. resp.getWriter().write(notLogin);
  35. return false;
  36. }
  37. //6.放行。
  38. log.info("令牌合法, 放行");
  39. return true;
  40. }
  41. @Override //目标资源方法运行后运行
  42. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  43. System.out.println("postHandle ...");
  44. }
  45. @Override //视图渲染完毕后运行, 最后运行
  46. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  47. System.out.println("afterCompletion...");
  48. }
  49. }

拦截器和过滤器区别:

1.接口规范不同,过滤器需要实现Filter接口,拦截器需要实现HandlerInterceptor接口

2.拦截范围不同,Filter会拦截所有资源,Interceptor只会拦截Spring环境中的资源

异常处理

建议使用全局异常处理器 主要两个注解,@RestControllerAdvice,表示当前类为全局异常处理器,@ExceptionHandler,指定要捕获的异常对象列别

  1. @RestControllerAdvice
  2. public class GlobalExceptionHandler {
  3. @ExceptionHandler(Exception.class)//捕获所有异常
  4. public Result ex(Exception ex){
  5. ex.printStackTrace();
  6. return Result.error("对不起,操作失败,请联系管理员");
  7. }
  8. }

事务

@Transactional注解:在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务,如果在这个方法执行的过程当中出现的异常,就会对事务进行回滚操作,可以写在方法上,类上,接口上。

可以在yml文件中开启事务管理日志,就可以看到事务的日志信息了

#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug
@Transactional注解里面可以传递两个属性,rollbackfor可以指定异常的类型,默认为运行时异常,我们可以将其设置成Exception.class。第二个属性是propagation用来配置事务的传播行为,常用的有以下几个,required:默认值,有则加入事务,无则创建事务。requires_new无论事务有无都创建一个新事务。

  1. @Service
  2. public class DeptLogServiceImpl implements DeptLogService {
  3. @Autowired
  4. private DeptLogMapper deptLogMapper;
  5. @Transactional(propagation = Propagation.REQUIRES_NEW)//事务传播行为:不论是否有事务,都新建事务
  6. @Override
  7. public void insert(DeptLog deptLog) {
  8. deptLogMapper.insert(deptLog);
  9. }
  10. }
  1. @Slf4j
  2. @Service
  3. //@Transactional //当前业务实现类中的所有的方法,都添加了spring事务管理机制
  4. public class DeptServiceImpl implements DeptService {
  5. @Autowired
  6. private DeptMapper deptMapper;
  7. @Autowired
  8. private EmpMapper empMapper;
  9. @Autowired
  10. private DeptLogService deptLogService;
  11. //根据部门id,删除部门信息及部门下的所有员工
  12. @Override
  13. @Log
  14. @Transactional(rollbackFor = Exception.class)
  15. public void delete(Integer id) throws Exception {
  16. try {
  17. //根据部门id删除部门信息
  18. deptMapper.deleteById(id);
  19. //模拟:异常
  20. if(true){
  21. throw new Exception("出现异常了~~~");
  22. }
  23. //删除部门下的所有员工信息
  24. empMapper.deleteByDeptId(id);
  25. }finally {
  26. //不论是否有异常,最终都要执行的代码:记录日志
  27. DeptLog deptLog = new DeptLog();
  28. deptLog.setCreateTime(LocalDateTime.now());
  29. deptLog.setDescription("执行了解散部门的操作,此时解散的是"+id+"号部门");
  30. //调用其他业务类中的方法
  31. deptLogService.insert(deptLog);
  32. }
  33. }
  34. //省略其他代码...
  35. }

这样无论操作成功还是失败,都会打印日志

AOP面向切面编程

首先要导入pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1.连接点 JoinPoint,可以被AOP控制的方法
2.通知Advice,共性逻辑,最终体现为一个方法

3.切入点PointCut,匹配连接点的条件,仅会在切入点方法执行时被应用

4.切面Aspect,通知+切入点,被@Aspect注解标识的类称为切面类

5.目标对象,通知所应用的对象

通知类型:

@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
@AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
@AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

里面可以有以下参数:

execution:execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)

简化:annotation自定义注解

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface MyLog {
  4. }

 Maven高级

分模块开发

新建pojo模块并引入lombok依赖,删掉tlias里的pojo包,util模块同理,然后再tlias的pom.xml里引入依赖

继承与聚合

创建一个父工程parent,让上面三个都继承他

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.7.5</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
  7. <groupId>com.itheima</groupId>
  8. <artifactId>tlias-parent</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>pom</packaging>

在子工程里,配置继承关系

  1. <parent>
  2. <groupId>com.itheima</groupId>
  3. <artifactId>tlias-parent</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. <relativePath>../tlias-parent/pom.xml</relativePath>
  6. </parent>
  7. <artifactId>tlias-utils</artifactId>
  8. <version>1.0-SNAPSHOT</version>

版本锁定

  1. <!--统一管理依赖版本-->
  2. <dependencyManagement>
  3. <dependencies>
  4. <!--JWT令牌-->
  5. <dependency>
  6. <groupId>io.jsonwebtoken</groupId>
  7. <artifactId>jjwt</artifactId>
  8. <version>0.9.1</version>
  9. </dependency>
  10. </dependencies>
  11. </dependencyManagement>

注意父工程中的dependencyManagement只能统一管理依赖版本,并不会直接引入依赖,所以子工程如果要使用这个依赖,依旧需要引入,只是此时无需指定版本号了

属性配置

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. <version>${lombok.version}</version>
  5. </dependency>
  1. <properties>
  2. <maven.compiler.source>11</maven.compiler.source>
  3. <maven.compiler.target>11</maven.compiler.target>
  4. <lombok.version>1.18.24</lombok.version>
  5. <jjwt.version>0.9.1</jjwt.version>
  6. <aliyun.oss.version>3.15.1</aliyun.oss.version>
  7. <jaxb.version>2.3.1</jaxb.version>
  8. <activation.version>1.1.1</activation.version>
  9. <jaxb.runtime.version>2.3.3</jaxb.runtime.version>
  10. </properties>
  11. <dependencies>
  12. <dependency>
  13. <groupId>org.projectlombok</groupId>
  14. <artifactId>lombok</artifactId>
  15. <version>${lombok.version}</version>
  16. </dependency>
  17. </dependencies>
  18. <!--统一管理依赖版本-->
  19. <dependencyManagement>
  20. <dependencies>
  21. <!--JWT令牌-->
  22. <dependency>
  23. <groupId>io.jsonwebtoken</groupId>
  24. <artifactId>jjwt</artifactId>
  25. <version>${jjwt.version}</version>
  26. </dependency>
  27. <!--阿里云OSS-->
  28. <dependency>
  29. <groupId>com.aliyun.oss</groupId>
  30. <artifactId>aliyun-sdk-oss</artifactId>
  31. <version>${aliyun.oss.version}</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>javax.xml.bind</groupId>
  35. <artifactId>jaxb-api</artifactId>
  36. <version>${jaxb.version}</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>javax.activation</groupId>
  40. <artifactId>activation</artifactId>
  41. <version>${activation.version}</version>
  42. </dependency>
  43. <!-- no more than 2.3.3-->
  44. <dependency>
  45. <groupId>org.glassfish.jaxb</groupId>
  46. <artifactId>jaxb-runtime</artifactId>
  47. <version>${jaxb.runtime.version}</version>
  48. </dependency>
  49. </dependencies>
  50. </dependencyManagement>

聚合

在parent中配置

  1. <!--聚合其他模块-->
  2. <modules>
  3. <module>../tlias-pojo</module>
  4. <module>../tlias-utils</module>
  5. <module>../tlias-web-management</module>
  6. </modules>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/272790
推荐阅读
相关标签
  

闽ICP备14008679号