当前位置: 首页>后端>正文

开发app时springboot框架 springboot框架原理

SpringBoot概述

设计目的:简化Spring应用初始搭建和开发过程。

特点(了解):

  1. 创建独立的Spring应用
  2. 嵌入的Tomcat,无需手动部署war文件
  3. 简化Maven的配置
  4. 自动配置Spring

SpringBoot = Spring(工厂)+SpringMVC(控制器)

SpringBoot2.2.5的环境搭建

环境要求

  1. MAVEN 3.3.x+
  2. JDK1.8 +

SpringBoot2.2.x+包装的是Spring框架5.x+

1. POM文件修改


<!--继承springboot的父项目-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
</parent>

<dependencies>
    <!--引入springboot的web支持-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>


2.加入配置文件

基础应用甚至可以不写配置文件,但也仅限于基础应用了……

配置文件的位置在src/main/resources/application.properties


# 修改内嵌服务器端口号,默认8080,可以不修改
server.port=8989
# 修改项目名,需要以斜杠开头,默认无项目名,可以不修改
server.servlet.context-path=/boot_day1


3.创建入口类


package com.baizhi; //注意入口类要在所有子包外面

@SpringBootApplication //用在类上,标识这是springboot的入口类
public class Day1Application {
    public static void main(String[] args) {
        //参数1:入口类对象 参数2:main函数的参数
        SpringApplication.run(Day1Application.class, args);
    }
}


SpringBoot入口类注解说明(了解)

@SpringBootApplication等价于以下三个注解的组合


@SpringBootConfiguration //启动SpringBoot应用时自动进行配置
@EnableAutoConfiguration //启动SpringBoot应用时对第三方引入的springboot相关依赖自动配置
@ComponentScan //用来扫描当前包和子包中的注解


4.开发控制器


@Controller
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/hello")
    @ResponseBody //SpringBoot默认没有集成JSP,之后会集成
    public String hello(){
        return "Hello Spring";
    }
}


SpringBoot管理对象

简单对象:@Component @Repository @Service @Controller ...

复杂对象(类中没有构造方法或者构造方法不能调用,如接口类型或抽象类实例):


@Configuration //这个注解表示这个类是一个配置类,相当于xml配置文件
public class BeansConfig {
    @Bean
    public Connection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/ajax?characterEncoding=UTF-8","root","1234");
    }
}


  • 使用复杂对象时一般按类型做自动注入即可。
  • 如果需要按名称做自动注入,默认的名称和方法名一致,可以使用@Bean("xxx")修改。

SpringBoot中集成jsp显示

1.引入依赖


<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>


2.配置视图解析器


# 配置前缀prefix和后缀.jsp
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp


补充:开发环境中启用jsp页面热部署

jsp页面热部署可以使得对jsp的修改无需重启服务器,但会略微降低整个应用的运行性能,如果项目上线后无需使用到这个功能,可以结合之后会讲的“配置分离”实现只在开发期间启用jsp热部署。


# 启用jsp页面热部署
server.servlet.jsp.init-parameters.development=true


SpringBoot和Mybatis整合

1.引入依赖


<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>


2.配置文件


# 数据源配置
# 连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 驱动类
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ajax?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=1234

# mybatis配置
# mapper文件位置
mybatis.mapper-locations=classpath:com/baizhi/mapper/*.xml
# 这个包里的类会自动成为别名
mybatis.type-aliases-package=com.baizhi.entity


3.入口类配置


@SpringBootApplication
@MapperScan("com.baizhi.dao") //自动注册Dao
public class Day1Application {
    public static void main(String[] args) {
        SpringApplication.run(Day1Application.class, args);
    }
}


4.Mybatis相关

建表、实体类、Dao、Mapper、Service省略

5.测试

引入测试依赖,注意:需要把junit的依赖去掉


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


测试类


@RunWith(SpringRunner.class)
@SpringBootTest(classes = Day1Application.class)
public class TestUserService {
    @Autowired
    private UserService userService;

    @Test
    public void test(){
        List<User> users = userService.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
}


也可以采用继承基础测试类的方式来减少冗余代码:


//基础测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Day1Application.class)
public class BasicTest {
}

//真正测试类
public class TestUserService extends BasicTest {
    @Autowired
    private UserService userService;

    @Test
    public void test(){
        List<User> users = userService.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
}


总结:环境搭建步骤

SpringBoot+JSP

  1. pom:
    ①父项目 spring-boot-starter-parent②依赖 spring-boot-starter-webtomcat-embed-jasperjstl
  2. 入口类:
    ①加注解@SpringBootApplication②写主函数SpringApplication.run(入口类.class, args)
  3. 配置文件 spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp

SpringBoot+Mybatis

  1. pom:
    ①父项目 spring-boot-starter-parent②依赖 spring-boot-starter-webmybatis-spring-boot-starterdruid数据库驱动(如mysql-connector-java)
  2. 入口类:
    ①加注解@SpringBootApplication @MapperScan("dao包名")②写主函数SpringApplication.run(入口类.class, args)
  3. 配置文件:
    spring.datasource.type=连接池 .driver-class-name=驱动类 .url=连接串 .username=用户名 .password=密码mybatis.mapper-locations=mapper文件位置 .type-aliases-package=实体类包名

SpringBoot 切面编程

引入依赖


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


相关注解

  • @Aspect 用在类上,代表这个类是一个切面的配置类
  • @Before 用在方法上,代表这个方法是一个前置通知方法
  • @AfterReturning 用在方法上,代表这个方法是一个返回后通知方法
  • @AfterThrowing 用在方法上,代表这个方法是一个异常通知方法
  • @Around 用在方法上,代表这个方法是一个环绕通知方法

@Before、@AfterReturning 、@AfterThrowing 、@Around的value属性值均是切入点表达式。

前置切面


@Aspect
@Component
public class MyAspect {
    @Before("execution(* com.baizhi.service.*ServiceImpl.*(..))")
    public void before(JoinPoint point){
        System.out.println("前置通知");
    }
}


返回后切面


@Aspect
@Component
public class MyAspect {
    //returning = "r" 表示形参中使用r接收返回值,如果不需要可以不写
    @AfterReturning(value = "execution(* com.baizhi.service.*ServiceImpl.*(..))", returning = "r")
    public void after(JoinPoint point, Object r){
        System.out.println("后置通知");
        System.out.println("返回值:" + r);
    }
}


异常切面


@Aspect
@Component
public class MyAspect {
    //throwing = "a" 表示形参中使用a接收抛出的异常,如果不需要可以不写
    @AfterThrowing(value = "execution(* com.baizhi.service.*ServiceImpl.*(..))", throwing = "a")
    public void afterThrowing(JoinPoint point, Throwable a){
        System.out.println("异常通知");
        System.out.println(a.getMessage());
    }
}


环绕切面


@Aspect
@Component
public class MyAspect {
    @Around("execution(* com.baizhi.service.*ServiceImpl.*(..))")
    public Object around(ProceedingJoinPoint point) {
        try {
            System.out.println("环绕 - 前");
            Object proceed = point.proceed();
            System.out.println("环绕 - 后");
            return proceed;
        }catch (Throwable a){
            System.out.println("环绕 - 异常");
            a.printStackTrace();
        }
        return null;
    }
}


补充知识:HTTP状态码

百科词条:HTTP状态码_百度百科

用来表示响应的状态。

常见状态码:

状态码

状态说明

备注

200

响应成功

304

未修改,可使用缓存

也是响应成功

400

请求有误

较常见的是参数格式不正确

403

无权限请求

404

请求路径未找到

500

服务器内部错误

通俗说,服务器代码抛异常了

SpringBoot的全局异常处理

请求路径未找到(404)

webapp目录建立文件夹error,在里面使用404.jsp作为找不到路径的显示页。

服务器内部错误(500)

方式一:error/500

webapp目录建立文件夹error,在里面使用500.jsp作为服务器内部错误的显示页。在这个页面,可以通过EL表达式${message}获取错误信息。

方式二:@ControllerAdvice + @ExceptionHandler


@ControllerAdvice
public class GlobalExceptionHandler {
    //可以书写多个方法来分别处理不同的异常,value值是个数组,里面是要处理的异常的类对象
    @ExceptionHandler(Exception.class) //处理所有的异常(Exception类和其子类)
    public String handlerException(HttpServletRequest request, Exception ex){
        ex.printStackTrace();
        request.setAttribute("errorMsg", ex.getMessage());
        return "error";
    }
    
    //可以书写多个方法来分别处理不同的异常,value值是个数组,里面是要处理的异常的类对象
    @ExceptionHandler({SqlException.class, IOException.class}) //处理Sql异常和IO异常(SqlException类和其子类、IOException类和其子类)
    public String handlerSqlAndIOException(HttpServletRequest request, Exception ex){
        ex.printStackTrace();
        request.setAttribute("errorMsg", "出错了!!!");
        return "error";
    }
}


另外,SpringBoot依然可以采用以下方式处理异常:

  1. 直接在Controller方法中try……catch:单独处理这个方法的异常,并且可以通过多个catch块实现不同异常不同处理。
  2. 使用拦截器的afterCompletion处理异常:可以针对不同路径采用不同的异常处理方式,并且可以配合instanceof实现不同异常不同处理。

SpringBoot的文件上传下载

本身不需要依赖,但如果需要且项目中没有org.apache.commons.io.IOUtilsorg.apache.commons.io.FilenameUtils这两个在上传下载业务中经常使用的工具类,则可以引入依赖:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

配置文件上传大小限制(不是必须的配置,但最好配置一下,因为默认值不一定符合项目需要):


# 单个文件最大大小
spring.servlet.multipart.max-file-size=500KB
# 整个请求最大大小
spring.servlet.multipart.max-request-size=2MB

# 大小单位
KB MB GB TB PB


编码部分和Spring MVC一致。

因为idea不会打包空文件夹,所以如果需要把用户上传的文件保存到项目里时,用于保存用户上传文件的文件夹内需要放一个任意文件来“占位”。

SpringBoot中的拦截器

拦截器开发部分和SpringMVC基本一致(区别:不需要工厂创建对象,且可以按照自己的需求实现以下任意方法):


public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        System.out.println("======1=====");
        return true;//返回true 放行  返回false阻止
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("=====3=====");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
        System.out.println("=====4=====");
    }
}


配置拦截器(和SpringMVC区别很大):


@Configuration //这个注解表示这个类是一个配置类,相当于xml配置文件
public class InterceptorConfig implements WebMvcConfigurer {
    //用来加入拦截器相关配置 参数1(registry): 拦截器注册对象
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/a/*") //拦截的路径,可以写多个
                .excludePathPatterns("/a/test2"); //放行的路径,可以写多个
        
        //可以添加多个拦截器
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") //拦截的路径,可以写多个
                .excludePathPatterns("/user/login", "/user/reg"); //放行的路径,可以写多个
    }
}


SpringBoot war包部署(了解)

大部分web项目部署,只需要使用maven-Lifecycle-package打成war包后部署到服务器就可以,但SpringBoot内嵌一个Tomcat服务器,因此改成外部服务器部署时需要额外做一些操作。

1.检查pom.xml确认打包方式为war


<packaging>war</packaging>


2.排除内嵌的tomcat

对于这种要临时修改pom依赖的情况,一定要做好记录和依赖搜索(先根据artifactId搜一下有没有这个依赖再按照下面的形式修改,不是直接把下面的依赖复制进去)

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <scope>provided</scope>   <!--去掉内嵌tomcat-->
</dependency>

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <scope>provided</scope>   <!--去掉使用内嵌tomcat解析jsp-->
</dependency>

3.修改入口类


//1. 继承SpringBootServletInitializer
public class Day1Application extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(Day1Application.class, args);
    }

    //2. 覆盖configure方法
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        //这里的参数是当前这个入口类的类对象
        return builder.sources(Day1Application.class);
    }
}


4. 进行打包

执行maven-Lifecycle-package来打包,然后target中就会出现项目的war包,可部署到tomcat根目录内的webapps文件夹进行测试和运行。

打包前会自动运行测试类代码,如果不想运行,可以使用“小闪电”图标切换为“跳过测试”模式(Toggle 'Skip Tests' Mode )

注意事项

一旦使用war包部署注意:application.properties中配置的server.portserver.servlet.context-path均失效,访问时使用打成war包的名字作为项目名(也可通过删除ROOT文件夹后,war包改名为ROOT.war来去掉项目名)和外部tomcat端口号进行项目访问。

logback日志集成(了解)

logback是由log4j创始人设计的又一个开源日志组件。目前,logback分为三个模块:logback-core,logback-classic和logback-access。是对log4j日志展示进一步改进。

logback中的概念

日志级别:OFF、FATAL、ERRORWARNINFODEBUG、ALL (从高到低),级别越高,输出的日志越少(比如设置为WARN时,是输出WARN、ERROR和FATAL级别)。

日志分类:根日志(rootLogger,全局日志)、分支日志(logger,包级别的日志),其中根日志必须存在。

SpringBoot中logback的使用

  1. SpringBoot中已经集成了logback,因此无需单独引入依赖
  2. application配置 # 日志配置
1. # 根日志级别
logging.level.root=error
# 单独某个包的分支日志级别
logging.level.com.baizhi=debug
# 关闭Mybatis的SQL语句输出
logging.level.com.baizhi.dao=error
# 日志写到这个文件,不需要输出到文件的话可以不写这个配置
logging.file.name=C:\MyComputer\SpringLog\aa.log
  1. 自己使用日志对象来输出日志 //成员变量中
//参数一般为当前类
private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
1. //想输出日志的地方
log.debug("debug");
log.info("info");
log.warn("warn");
log.error("error");
//也可以采用{}占位符输出形式
log.info("name: {}, id: {}", user.getName(), user.getId());

SpringBoot中配置文件的拆分(了解)

在实际开发过程中生产环境和开发环境的配置有可能是不一样的,因此将生产中的配置和开发中的配置拆分开是非常必要的。

配置拆分由一个主配置文件application.properties和多个子配置文件application-xxx.properties组成,主配置文件可以决定让哪个子配置文件生效。

子配置文件会对主配置文件进行智能的整合和覆盖,因此进行配置文件拆分后,写起来依然比较灵活。

整合和覆盖的规则:

  • 子配置文件中不存在的配置项,会使用主配置文件 - 整合。
  • 子配置文件会覆盖主配置文件的同一配置项 - 覆盖。

例如:

主配置文件application.properties


server.port=8989
# 当前使用的子配置文件为application-dev.properties
spring.profiles.active=dev

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp


开发配置文件application-dev.properties


server.port=10010
server.servlet.context-path=/dev_day1
server.servlet.jsp.init-parameters.development=true


生产配置文件application-prod.properties


server.port=8888


配置效果:

  • 当主配置文件中spring.profiles.active=dev时,端口为10010(来自于dev子配置对主配置的覆盖),项目名为/dev_day1(直接来自于dev子配置),启用了jsp热部署(直接来自于dev自配置),视图前后缀为/.jsp(来自于主配置)。
  • 当主配置文件中spring.profiles.active=prod时,端口为8888(来自于prod子配置对主配置的覆盖),视图前后缀为/.jsp(来自于主配置)。

https://www.xamrdz.com/backend/33e1962966.html

相关文章: