四、Springboot

Springboot

  • 2014年推出第一个版本,Springboot主要的目的是简化Spring框架开发的过程

  • 开发理念是约定大于配置

  • 优点

    • 简化Spring框架开发环境的搭建
    • 没有xml配置
    • 通过stater的设计,简化了maven管理的依赖
    • 简化了应用的部署,Springboot框架内部自己封装了tomcat、jetty等服务器
    • 可以快速的构建和启动一个Web应用
  • Springboot项目的构建方式

    • 在官网上通过quick start构建
    • 直接创建一个maven项目进行构建,需要手动导入Springboot的依赖
  • 以maven方式项目构建

    • 引入基础核心依赖

      <!--继承springboot的父项目-->
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>2.1.3.RELEASE</version>
          </parent>
      
          <dependencies>
              <!--引入springboot的web支持-->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
          </dependencies>
      
    • Springboot项目的目录结构约定

      • 目录结构

        • com
          • |-mo
            • |-entity、dao、service、controller、启动类App:这个启动类启动时,会扫描同级位置包结构下的spring相关注解,同时还会启动springboot内部的tomcat,位置必须与dao、service、controller这些包同级,或者这些包的父目录上
      • 配置文件 —> application.properties / application.yml / application.yaml

        • 配置文件位置要在项目的根目录

          //和二级目录在一块 app.java
          /**
           * 用注解声明当前类是一个启动类
           */
          @SpringBootApplication
          public class App {
              public static void main(String[] args) {
                  //指定启动类,运行后会启动整个Web应用
                  SpringApplication.run(App.class,args);
              }
          }
          
          //配置文件根目录下 application.properties
          #指定springboot内置tomcat启动的端口号
          server.port=8989
          
          @RestController //相当于@Controller+@ResponseBody
          @RequestMapping("hello")
          public class HelloController {
              @RequestMapping("mo")
              //@ResponseBody
              public String mo(){
                  System.out.println("hello springboot");
                  return "success";
              }
          }
          
          //当两个配置文件同时存在,则application.properties优先加载,不建议两种配置文件同时存在
          //application.yml
          #自定义服务器启动的端口
          server:
            port: 8989		//空格必须要有
            servlet:
              context-path: /demo1		//空格必须要有
          #springmvc的jsp解析器
          spring:
            mvc:
              view:
          	  preifx: /
                suffix: .jsp
            datasource:
              type:com.alibaba.druid.pool.DruidDataSource
              driver-class-name:oracle.jdbc.OracleDriver
              url:jdbc:oracle:thin:@10.211.55.3:1521.xe
              username:hr
              password:hr
          mybatis:
            mapper-locations:classpath:com/mo/mapper/*Mapper.xml
            type-aliases-package:com.mo.entity
          
@SpringBootApplication注解
  • 是由@SpringBootConfiguration、EnableAutoConfiguration、ComponentScan集成

    • @SpringBootConfiguration:启动Springboot框架的配置功能,指定当前是个启动类
    • @EnableAutoConfiguration:开启自动配置,将当前类声明为一个Spring的配置类
    • @ComponentScan:自动到启动类的同级包结构下扫描相关的注解;扫描使用了Spring开发注解的包,扫描的范围是同级位置的包以及同级位置下的子包
  • Springboot底层实现方式之一,java bean配置形式

    <bean id="u" class="com.mo.service.UserServiceImpl"></bean>
    
    //等价
    @Configuration
    public class FactoryConfig{
    	@Bean	//将当前方法的返回值对象纳入Spring工厂管理
    	public UserServiceImpl u(){	//此时通过工厂getBean获取对象时,id为方法名u
    		return new UserServiceImpl();
    	}
    }
    
整合JSP
  • 引入依赖

  • Springboot启动类默认启动的时候不会将jsp或html打包运行,需要手动配置启动的工作项目目录

    • Edit Configurations —> Enviroment —> Working directory

    • 也可以插件的方式启动

      <!--引入jsp运行插件-->
      <plugins>
            <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
      </plugins>
      
    • 还可以以jar包形式启动

  • 项目的基本配置

    • App.java

      /**
       * 用注解声明当前类是一个启动类
       */
      @SpringBootApplication
      //指定dao接口所在的包结构
      @MapperScan("com.mo.dao")
      public class App {
          public static void main(String[] args) {
              //指定启动类,运行后会启动整个Web应用
              SpringApplication.run(App.class,args);
          }
      }
      
    • Dao.java

      @Repository
      public interface EmpDao {
      }
      
    • application.properties

      #指定springboot内置tomcat启动的端口号
      server.port=8989
      
      #编写视图解析器
      spring.mvc.view.prefix=/
      spring.mvc.view.suffix=.jsp
      
      #整合mybatis相关的内容
      spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
      spring.datasource.url=jdbc:oracle:thin:@10.211.55.3:1521:xe
      spring.datasource.username=hr
      spring.datasource.password=hr
      #数据源
      spring.datasource.type=org.apache.commons.dbcp.BasicDataSource
      
      #指定mapper文件路径
      mybatis.mapper-loactions=classpath:com/mo/mapper/*Mapper.xml
      #指定实体类别名
      mybatis.type-aliases-package=com.mo.entity
      
设置springboot日志级别
  • Springboot默认集成了logback日志工具,logback是log4j作者开发的一个产品,在效率上比log4j更高,升级版日志管理

  • 关于日志常用的几种级别:

    • DEBUG --> INFO --> WARN --> ERROR,四种日志级别由低到高,级别越低输出信息越多,级别越高输出的信息越少

    • root(父日志):代表根目录,会全面监控项目中所有位置的日志处理输出

    • logger(子日志):用于监控指定位置下的日志的处理输出,主要区别为范围

      #自定义日志输出级别
      logging:
      	level:
      		root: info 	#springboot默认日志级别		root,整个项目范围内所有的日志级别
      		com.mo.dao: DEBUG		#便于查看mybatis		针对某些特定的包设置日志级别
      		com.mo: DEBUG		#此时包含子目录
      		
      #书写日志配置
      logging.level.root=info
      logging.level.com.mo.controller=debug
      logging.level.com.mo.service=debug
      #指定日志输入文件名,默认会在当前项目的根目录下生成日志文件
      logging.file=log.log
      #指定一个输出日志文件的目录,不需要指定文件名,默认日志文件名为spring.log
      #当指定了logging.file后logging.path的配置会失效
      #logging.path=d://
      
    • 程序中测试,在哪个阶段查看

      @Controller
      @ReqeustMapping("emp")
      @Slf4j	//测试日志
      public String findAll(Model model){
      	//private Logger log = LoggerFactory.getLogger(EmpController.class);有@Slf4j注解时不需要写
      
      	@Autowired
      	private EmpService empService;
      	
      	List<Emp> emps = empService.findAll();
      	model.addAttribute("emps",emps);
      	//System.out.println()做测试时,因为调用的是IO,效率低,不采用
      	//使用日志调试项目
      	//log.debug("{}",emps)	设置了debug级别,比debug低的都不会输出
      	log.info("{}",emps);
      	
      	return "list";
      }
      
    • 测试

      @RunWith(SpringRunner.class)	//相当于SpringJuntiClassRunner的功能
      @SpringBootTest(classes = {SpringbootDemo2App.class})	//指定启动类
      public class TestEmpService{
      	@Autowired
      	private EmpService empService;
      	
      	@Test
      	public void test0(){
      		List<Emp> all = empService.findAll();
      		System.out.println(all);
      	}
      }
      
  • 自定义日志监控模版

    logback.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
    	<!-- appender代表配置的一个日志输出方式(日志在控制台输出还是输出到一个文件)和输出格式的模版
    	ConsoleAppender:用于将日志输出到控制台-->
    	<appender name="sout" class="ch.qos.logback.core.ConsoleAppender">
    		<!-- 指定输出日志格式处理的类 -->
    		<layout class="ch.qos.logback.classic.PattrenLayout">
    			<!-- 具体指定日志输出的格式模版-->
    			<pattern>%d{yyyy-MM-dd HH:mm:ss} %p %r [%t] %m %n</pattern>
    		</layout>
    	</appender>
    	<!-- root根日志处理,通常只有一个
    	logback只会处理包含当前日志输出级别以及比他高的级别的日志输出 -->
    	<root level="info">
    		<!-- 引用日志的输出处理模版-->
    		<appender-ref ref="sout"></appender-ref>
    	</root>
    	<!-- logger子日志处理,子日志监控可以有多组配置 -->
    	<logger name="com.mo.dao"></logger>
    </configuration>
    
配置文件按照不同环境的选择
  • application.yml:项目的发布可以灵活切换

    • application-dev.yml:开发环境

    • application-prod.yml:线上环境

      spring:
      	profiles:
      		active: dev	//此时使用dev
      		
      spring:
      	profiles:
      		active: prod	//此时使用prod
      	
      或
      spring.profiles.active=dev
      
热部署
  • 引入热部署依赖:有可能遇到问题,涉及到虚拟机

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-devtools</artifactId>
    </dependency>
    
  • idea设置:Build,Execution,Deployment --> Compile --> 钩上Build project automatically

Springboot三种启动方式
  • 启动类方式启动:要求启动类上面使用@SpringBootApplication

  • 使用插件方式启动

  • 打成war包部署到外部tomcat:需要手动排除Springboot内置的tomcat,然后打包

    • 排除内部tomcat

      <!--引入springboot的web支持-->
      <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
              <!--排除内部的tomcat-->
              <exclusions>
                      <exclusion>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-starter-tomcat</artifactId>
                      </exclusion>
             </exclusions>
      </dependency>
      
    • 给App换一个启动方式:继承SpringBootServletInitializer,覆盖configure方法,使用SpringApplicationBuilder启动

      @SpringBootApplication
      public class App extends SpringBootServletInitializer {
      	//使用builder方式启动应用
      	@Override
      	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder){
      		return builder.source(App.class);
      	}
      }
      
  • 以jar包的形式启动

    • 手动将pom中的packaging改成jar,代表以jar包的方式打包项目
    • 执行mvn package进行打包,然后可以将打好的jar包直接放到一个具备java环境的服务器上运行
    • 执行jar包启动java -jar 指定springboot项目的jar包运行
    • jar包方式部署一般只给前端提供数据,主要用于前后端分离开发的项目,不做视图(JSP、HTML资源的部署),适合微服务和集群部署
  • docker技术做微服务,需要jar包方式

  • 编码格式的处理

    • POST请求中文乱码处理

      #开启http请求编码的处理,默认为true
      spring.http.encoding.enabled=true
      
      #application.properties
      #POST请求中文编码
      spring.http.encoding.charset=UTF-8
      
    • GET请求中文乱码

      #application.properties
      
      #修改springboot项目内置tomcat对get请求中文乱码的处理
      server.tomcat.uri-encoding=UTF-8
      
    • 插件乱码问题

      <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
              <!--避免乱码,给插件指定编码格式 -->
              <configuration>
                          <!--强制使用这些参数-->
                          <fork>true</fork>
                          <jvmArguments>-Dfile.encoding=utf-8</jvmArguments>
                          <!--指定启动类-->
                          <mainClass>com.mo.App</mainClass>
              </configuration>
      </plugin>
      
  • 自定义JSON中日期转换格式

    public class User implements Serializable {
        private String username;
        private String password;
        //自定义JSON转换中日期类型的格式
        @JsonFormat(pattern = "yyyy-MM-dd")
        private Date date;
    }
    
    @RequestMapping("test0")
    //@ResponseBody
    public String test0(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
            System.out.println("test0:"+date);
            return "index";
    }
    
  • 接收日期格式也可以在配置文件中设置

    #application.properties
    spring.mvc.data-format=yyyy-MM-dd
    
AOP开发
  • 前置通知

    • 编写切面类

      //把这个类装入spring工厂
      @Component
      // 将当前类定义为切面类
      @Aspect
      public class BeforeAdvice {
          
          // 前置通知,里面写切入点函数
          @Before("execution(* com.mo.service..*.*(..))")
          public void beforeAdvice(JoinPoint joinPoint){
              //书写额外功能
              System.out.println("额外功能的实现");
              // 原始方法参数
              Object[] args = joinPoint.getArgs();
              // 原始方法签名
              Signature signature = joinPoint.getSignature();
              // 原始类的对象
              Object target = joinPoint.getTarget();
              System.out.println("args原始方法参数:"+args[0]);
              System.out.println("signature原始方法签名:"+signature.getName());
              System.out.println("target原始类的对象:"+target.getClass());
          }
      }
      
  • 后置通知

    @Component
    @Aspect
    public class MyAfterAdvice {
        //会把返回值注入
        @AfterReturning(pointcut = "execution(* com.mo.service..*.*(..))",returning = "result")
        public Object afterAdvice(JoinPoint joinPoint,Object result){
            System.out.println("额外功能后置通知");
            
            return result;
        }
    }
    
  • 环绕通知

    @Component
    @Aspect
    @Slf4j
    public class AroundAdvice {
        @Around("execution(* com.mo.service..*.*(..))")
        public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            //原始方法前额外功能
            System.out.println("环绕功能的前额外功能");
            log.info("原始方法调用日志记录");
            //手动调用原始方法
            //proceedingJoinPoint与前置通知使用一致
            Object o = proceedingJoinPoint.proceed();
            // 原始方法后额外功能
            System.out.println("环绕功能的后额外功能");
            return null;
        }
    }
    
文件上传
  • springboot自动导入依赖

  • application.properties

    #定义上传文件大小限制
    #上传单个文件大小限制,默认1M,单位为字节
    spring.servlet.multipart.max-file-size=20971520
    #一次请求总的上传文件大小限制,默认10M,单位为字节
    spring.servlet.multipart.max-request-size=20971520
    
  • jsp

    <form action="${pageContext.request.contextPath }/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="upload">
        <input type="submit" value="上传">
    </form>
    
  • controller

    @Controller
    @RequestMapping("file")
    public class FileController {
        
        @RequestMapping("upload")
        public String upload(MultipartFile upload, HttpSession session) throws IOException {
            //获取保存文件的位置,真是路径
            String realPath = session.getServletContext().getRealPath("/upload");
            String filename = upload.getOriginalFilename();
            // 保存文件
            upload.transferTo(new File(realPath+"/"+filename));
            return "index";
        }
    }
    
文件下载
  • controller

    @RequestMapping("download")
    public void download(HttpServletResponse response,HttpSession session) throws IOException {
            //读取待下载文件
            String realPath = session.getServletContext().getRealPath("/upload");
            FileInputStream in = new FileInputStream(realPath + "/5.jpg");
            //设置两个请求头:指定下载文件的类型,下载文件的保存 / 打开方式
            response.setHeader("content-type", "image-jpeg");
            response.setHeader("content-disposition","arrachment;filename=a.jpg");
            IOUtils.copy(in,response.getOutputStream());
    }
    
拦截器
  • 编写拦截器

    public class MyInterceptor1 implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("pre handler");
            
            //true执行
            return true;
        }
    }
    
  • 注册拦截器,javabean形式

    //作为一个配置类加入到Spring中
    @Component
    public class RegistInterceptor implements WebMvcConfigurer {
        /**
         * 注册拦截器
         * @param registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            InterceptorRegistration interceptor = registry.addInterceptor(new MyInterceptor1());
            //配置拦截的范围
            interceptor.addPathPatterns("/**"); //拦截所有
            //路径不能带项目名
            interceptor.excludePathPatterns("/target/test0");     //排除不拦截的,基于上面的范围排除
        }
    }
    
全局异常处理
  • 使用注解定义全局异常处理器

    //声明为一个异常处理类,当程序运行过程中出现指定的异常类型,会自动进入全局的异常处理器,执行对应的异常处理方法
    @ControllerAdvice
    public class ExceptionHandlerController {
        //参数是异常类型的类对象数组
        @ExceptionHandler(NullPointerException.class)
        public String handleNullPointerException(Exception e){
            //输出此时的异常,便于调错
            e.printStackTrace();
            System.out.println("异常处理器 1");
            return "redirect:/error.jsp";
        }
        //匹配优先级是先精确匹配,然后在匹配大范围
        @ExceptionHandler(Exception.class)
        public String handleException(Exception e){
            //输出此时的异常,便于调错
            e.printStackTrace();
            System.out.println("异常处理器 2");
            return "redirect:/error.jsp";
        }
    }
    
跨域问题
  • 发生在js代码中向不是同一个应用(域名或IP或端口有一个不一致就属于不同的应用)的资源发起请求,获取数据的情况;跨域问题是浏览器提供的一种安全策略,不允许随便都能获取网站的数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值