SpringBoot 03 Web开发

SpringBoot 代替了SSM整合,避免了版本依赖冲突,不在需要手写配置文件


前言

springboot提供了starter场景启动器(web,Tomcat,jdbc),自带相关组件实现自动配置

场景启动器   启动项目直接在idea中勾选相关场景自动配置,如 springboot-starter-xxx 都是场景,非官方场景启动器建议命名形式为 xxx-springboot-starter。相关场景启动器已做好相关依赖,可以不在pom文件中定义版本号,需要修改可以使用就近原则声明自定义版本


SpringBoot约定大于配置,相关依赖参考官方文档 ,修改场景启动器的默认配置可以修改配置文件或者自定义组件实现。

一、SpringBoot基础

1.自动配置

SpringBoot启动从主程序开始,注解  @SpringBootApplication 包含3个注解

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

其中 @SpringBootConfiguration 用于加载Configuration配置类,@EnableAutoConfiguration    是重点观察。该注解导入了类AutoConfigurationImportSelector

@Import({AutoConfigurationImportSelector.class})

2.生命周期

  1. 初始化阶段:加载配置文件(application.properties , application.yml)、准备环境。
  2. 上下文刷新阶段:初始化 Spring 容器、注册 Bean。
  3. 应用运行阶段:启动嵌入式服务器,监听请求。
  4. 关闭阶段:释放资源,执行销毁回调。

 

3.声明式事务

不同于排查错误相对容易的编程式(代码),声明式(注解)可以使用少量代码快速上手封装功能组件。

直接在启动类中新增注解 @EnableTransactionManagement 开启事务,在Service层涉及事务方法新增注解@Transactional  即可。@Transactional可以进行rollbackfor({Exception.class}) 处理。

隔离级别(isolation)(Mysql的默认隔离级别是 可重复读Repeatable read

事务传播行为(propagation)定义 如何使用事务,即当前事务是否和所在嵌套的大事务一同回滚

 参数设置项(e.g. timeout=5)也按传播行为决策,小事务与大事务关系同样决定参数设置项。

二、回顾

1.SpringMVC回顾

Web应用核心就是处理http请求与响应。springMVC代替了传统三层模型中View层的控制器controller(handler),具体就是使用更易用的 DispatcherServlet代替了原生servlet,具体参考专栏笔记合集。通过使用RequestMapping注解实现与前端URL交互,并且RequestMapping注解参数支持ant风格通配符(精确匹配优先)(* 代表handler接受请求的参数中包含任意字符; **代表handler接受请求的参数中包含任意目录 ; ?代表handler接受请求的参数中包含一个任意形式的字符)。

springMVC官方文档地址 ,显示其基于Servlet API并开始被包含在spring框架中(spring-webmvc),也被成为Spring MVC。重点需要关注的有以下几点:

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, "Spring Web MVC," comes from the name of its source module (spring-webmvc), but it is more commonly known as "Spring MVC".

 代码中使用@RequestBody 将请求体的JSON数据写入pojo类中;常使用  @RestController 替代 @Controller 与 @Responsebody;当需要接收前端传输的文件,使用@RequestParam注解与Multipartfile类(Multipartfile file/Multipartfile files[]),配置文件调整单个文件和总文件上传大小:

spring.servlet.multipart.max-file-size= 1GB

spring.servlet.multipart.max-request-size= 10GB

其他相关注解如图: 

@PathVariable-路径变量
/resources/{name}:最多使用
{} 中的值封装到 name 变量中 

PathVariable支持正则表达式

//@RequestBody 封装pojo对象

  @PostMapping
    public ResponseMessage add(@Validated @RequestBody UserDTO userDto) {
        User user = userService.addUser(userDto);
        return ResponseMessage.sucess(user) ;
    }

http相关内容补充:

传统使用  request.getParameter  方式获取请求参数信息request.getHeader 方式获取请求头信息,spring使用@requestParam注解实现获取请求参数,@CookieValue(“”)获取cookie内容 。

当引入JSON:后,JSON是一种字符串数据格式,也可以作为对象,这使JSON作为序列化/反序列化都很方便。适合作为前后端交互的传输数据格式,用@RequestBody序列化请求体JSON对象。

HttpEntity<T> 作为方法参数,T可以变为pojo类火String,但是用的比较少。


springMVC处理响应:

@ResponseBody 把返回的内容写入响应体中;与文件上传对应,文件下载的响应方式为固定格式方法返回类型为 ResponseEntity<byte[]>. 自定义响应头,encode编码解决中文名称乱码;使用InputStreamResource封装传入对应文件输入流解决文件过大。固定写法如图:

 

2.SpringBoot回顾

RESTful风格

之前的简单demo中使用了RESTful风格,具体见这里。本质是对资源状态变化的操作。 

提及的三层(control,service,dao/repository)不再赘述, 

统一异常处理代码如下 :

public class ResponseMessage<T> {
    private Integer code;
    private String message;
    private T data;


    public static <T> ResponseMessage<T> sucess(T data) {

        ResponseMessage response = new ResponseMessage();
        response.setCode(HttpStatus.OK.value());
        response.setMessage("success");
        response.setData(data);
        return response;
    }

.......//此处省略get/set方法与有参/无参构造方法
  }

跨域-CORS(跨源资源共享) 策略

前后端分离项目 浏览器 要求要去的服务器与项目所在的服务器必须是同一个源;

后端解决方式在响应头中增加Access-Control-Allow-0rigin = *,在代码直接新增注解。


三、一些补充

1.拦截器

SpringMVC内置拦截器机制,可以对请求目标方法执行前/后进行拦载,执行额外操作,比如:权限验证、日志记录、数据共享等...(filter拦截servlet,拦截器拦截controller的方法)参考文章
使用步骤:
1.实现 Handlerinterceptor 接囗的组件即可成为拦截器

@Component
public class MyHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyHandlerInterceptor.preHandle");
        return true ; //HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        System.out.println("MyHandlerInterceptor.postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    System.out.println("MyHandlerInterceptor.afterCompletion");}
}

preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行

postHandle方法:目标资源方法执行后执行

afterCompletion方法:视图渲染完毕后执行,最后执行

2.创建 WebMvcConfigurer 组件,并配置拦截器的拦截路径

@Configuration
public class DSConfig implements WebMvcConfigurer {

    @Autowired
    MyHandlerInterceptor myHandlerInterceptor;
    //添加拦截器 InterceptorRegistry 拦截器注册类
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myHandlerInterceptor)
        .addPathPatterns("/**");  //链式调用,拦截所有请求
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

査看执行顺序效果:preHandle =>目标方法=>postHandle =>aftercompletion

 发送一个get请求后控制台信息如图

  

2.异常处理

不在推荐使用编程式异常处理(try...catch...),现代通常使用声明式异常处理 ;如果controller类有异常出现,对应注解 (@ExceptionHandler({Exception.class}))自动识别进行处理;代码如下:


@RestControllerAdvice
public class GlobalExceptionHandlerAdvice {

    Logger logger = LoggerFactory.getLogger(GlobalExceptionHandlerAdvice.class);
    @ExceptionHandler({Exception.class})
    public ResponseMessage handleException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        logger.error("统一异常: "+e.getMessage(), e);
        return new ResponseMessage(500,"erro",null);
    }
}

类上的注解  @RestControllerAdvice 为全局异常处理注解,是对@RestController注解的增强

最终异常处理,前端关系异常状态,后端关注正确的业务流程。因此实际开发 后端只编写正确的业务逻辑 ,异常出现首先中断业务,抛出业务异常(BizException)异常处理的最终方式:


1、必须有业务异常类:BizException

2、必须有异常枚举类:BizExceptionEnume列举项目中每个模块将会出现的所有异常情况

3、编写业务代码的时候,只需要编写正确逻辑,如果出现预期的问题,需要以抛异常的方式中断逻辑并通知上层。

全局异常处理器:GlobalExceptionHandler;处理所有异常,返回给前端约定的json数据与错误码

3.数据校验

JSR303规范(JavaBean校验规范)与前端校验同时使用。 相关校验代码写入DTO层中,如下:


public class UserDTO {

@NotBlank(message = "name is null")
    private  String userName;
    @NotBlank(message = "password is null")
    @Length(max = 12,min = 6)
    private  String password;
    @Email(message =  "email format erro")
    private  String email;
.....
}

controller层方法调用相关方法使用 注解@Validated 开启校验

 @PostMapping
    public ResponseMessage add(@Validated @RequestBody UserDTO userDto) {
        User user = userService.addUser(userDto);
        return ResponseMessage.sucess(user) ;
    }

使用BindingResult类封装校验信息,在统一异常中返回Map封装,实现全局异常处理机制。

4. 补充与总结

VO

POJO(普通Java类)  DAO(数据库访问对象)DTO(数据传输对象)VO(视图/值对象) BO(业务对象)

vo(EditDTO)与前端交互实现数据脱敏。使用 BeanUtils方法传递xxO的数据到实体类中

        BeanUtils.copyProperties(user,userPojo);
knief4j接口文档:

现代(遵循openAPI规范)普遍使用基于swagger的knief4j工具转接口文档,官网地址 。常用注解:

Maven坐标:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

 配置文件信息(properties.yml):

# springdoc-openapi项目配置
springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'default'
      paths-to-match: '/**'
      packages-to-scan: org.jac.accountability.controller
# knife4j的增强配置,不需要增强可以不配
knife4j:
  enable: true
  setting:
    language: zh_cn

在controller类上新建注解 

@Tag(name="用户控制器")

 启动项目后直接访问 http://localhost:8088/doc.html  可获取对应接口文件.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值