当前位置: 首页 > news >正文

好看的企业网站首页崇明集团网站建设

好看的企业网站首页,崇明集团网站建设,唐山中企动力做网站,淘宝网站建设不允许SpringBoot讲义 什么是SpringBoot#xff1f; Spring Boot是由Pivotal团队提供的全新框架#xff0c;其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置#xff0c;从而使开发人员不再需要定义样板化的配置。通过这种方式#xf… SpringBoot讲义 什么是SpringBoot Spring Boot是由Pivotal团队提供的全新框架其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置从而使开发人员不再需要定义样板化的配置。通过这种方式Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。 Spring 从4.x版本开始提倡java配置和注解结合使用慢慢离开xml繁琐的配置所以要入门SpringBoot需要从java配置开始。在Spirng Boot和Spring Cloud中大量使用了注解与JavaConfig。 JavaConfig诞生的原因是什么 Spring IOC有一个非常核心的概念——Bean。由Spring容器来负责对Bean的实例化装配和管理。早些时候XML是用来描述Bean最为流行的配置方式。随着Spring的日益发展由于Spring会把几乎所有的业务类都以Bean的形式配置在XML文件中造成了大量的XML文件。使用XML来配置Bean失去了编译时的类型安全检查。大量的XML配置使得整个项目变得更加复杂。 当随着JAVA EE 5.0的发布其中引入了一个非常重要的特性——Annotations(注解)。注解是源代码的标签这些标签可以在源代码层进行处理或通过编译器把它熔入到class文件中。在JAVA EE 5以后的版本中注解成为了一个主要的配置选项。Spring使用注释来描述Bean的配置与采用XML相比因类注解是在一个类源代码中可以获得类型安全检查的好处。可以良好的支持重构。 JavaConfig就是使用注解来描述Bean配置的组件。JavaConfig 是Spring的一个子项目。 JavaConfig常见的注解有哪些 Configuration注解 该注解贴在类上表示是一个配置类。相当于xml配置 Bean注解 Bean是一个方法级别上的注解主要用在Configuration注解的类里也可以用在Component注解的类里。添加的bean的id为方法名 也可以执行生命周期的回调函数类似PostConstruct初始化方法 和 PreDestroy销毁方法的方法 Scope注解 Scope 注解用来设置交给spring容器管理的Bean是单例方式还是多例方式 相当于bean标签中的scope属性 ComponentScan注解 创建一个配置类在配置类上添加 ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类相当于之前的xml context:component-scan。 Import注解 Import(要导入到容器中的组件)容器中就会自动注册这个组件id默认是全类名 ImportResource注解 ImportResource和Value进行资源文件读取 PropertySource value 注解 Spring框架提供了PropertySource注解目的是加载指定的属性文件 Value 可以获取配置文件中的值 ProfileActiveProfile注解 profile注解是spring提供的一个用来标明当前运行环境的注解。我们正常开发的过程中经常遇到的问题是开发环境是一套环境QA测试是一套环境线上部署又是一套环境。这样从开发到测试再到部署会对程序中的配置修改多次尤其是从QA到上线这个环节让QA的也不敢保证改了哪个配置之后能不能在线上运行。 为了解决上面的问题我们一般会使用一种方法就是配置文件然后通过不同的环境读取不同的配置文件从而在不同的场景中跑我们的程序。 那么spring中的profile注解的作用就体现在这里。在spring使用DI来依赖注入的时候能够根据当前制定的运行环境来注入相应的bean。最常见的就是使用不同的DataSource了。 JavaConfig配置的应用场景 在IOC中 需求一把一个Bean交给Spring管理 回顾使用xml配置方式 applicationContext.xml: ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd bean idsomeBean classcn.wolfcode.javaconfig._01_xmlconfig.SomeBean/ /beans SomeBean: public class SomeBean {public void print() {System.out.println(print xmlConfig);} } XMLConfigTest: public class XMLConfigTest {Testpublic void testXMLConfig() throws Exception {// 加载spring的配置文件ApplicationContext ctx new ClassPathXmlApplicationContext(cn/wolfcode/javaconfig/_01_xmlconfig/applicationContext.xml);// 通过spring容器获取SomeBeanSomeBean someBean ctx.getBean(SomeBean.class);// 执行print方法someBean.print();}}使用javaConfig方式 Configuration :spring的配置标签打在哪个类上这个类就表示spring的配置类 相当于applicationContext.xml文件 Bean :打在方法上方法返回的实例对象交给spring容器管理方法的名称就是Bean标签中的id值。 相当于配置文件中bean标签。 如 bean idsomeBean classcn.wolfcode._01xmlconfig.SomeBean /ApplicationConfig: Configuration public class ApplicationConfig {Beanpublic SomeBean someBean(){return new SomeBean();} }SomeBean: public class SomeBean {public void print(){System.out.println(print JavaConfig);} } 这里不再是通过xml配置文件获取spring容器对象而是通过加载配置类。因此应该选用 AnnotationConfigApplicationContext 类加载配置类的字节码文件。 JavaConfigTest: public class JavaConfigTest {Testpublic void testJavaConfig() throws Exception {// 加载配置类ApplicationContext ctx new AnnotationConfigApplicationContext(ApplicationConfig.class);// 从spring容器中获取SomeBean对象SomeBean someBean ctx.getBean(SomeBean.class);// 打印someBean.print();} }ComponentScan 使用该注解改良代码。 通过上述的案例其实我们发现上面的写法也显得很麻烦。还不如使用配置文件简洁。 在配置类中通过给方法添加注解Bean把该方法的返回值交给spring管理。代码量太大如果需要交给Spring管理很多Bean的话我们要写很多个方法在配置类中。 在javaConfig中给我们提供一个注解ComponentScan可以把需要管理的Bean 贴上注解Component,然后通过在配置类上面贴注解ComponentScan来进行扫描贴了注解的Bean然后把这些Bean交给Spring管理。 ComponentScan 这个标签也相当于之前在配置文件中的配置的 context:component-scan base-package / //开启 ioc组件自动扫描功能注意ComponentScan注解也可以通过配置指定扫描哪个包。 如ComponentScan(cn.wolfcode)表示扫描“cn.wolfcode”这个包以及它下面的子包把包中的贴了注解的Bean 交给spring容器管理。如果不指定包表示扫描当前包以及下面的子包改良方案如下 ApplicationConfig Configuration ComponentScan(cn.wolfcode.javaconfig._03_scan) public class ApplicationConfig {}JavaConfigTest public class JavaConfigTest {Testpublic void testJavaConfig() throws Exception {// 加载配置类ApplicationContext ctx new AnnotationConfigApplicationContext(ApplicationConfig.class);// 从spring容器中获取SomeBean对象SomeBean someBean ctx.getBean(SomeBean.class);// 打印someBean.print();} }SomeBean Component public class SomeBean {public void print(){System.out.println(print ScanConfig);} }Bean中的一些属性的补充 属性initMethod 该属性相当于bean标签中的initMethod属性用来设置bean被初始化所调用的方法。 如 bean idsomeBean class init-methodinit /属性destroyMethod 该属性相当于bean标签中的destroyMethod 属性用来设置bean被销毁时执行的操作。 如 bean idsomeBean class destroy-method /注意必须是容器正常关闭销毁bean才会调用销毁方法。 使用普通的junit测试是不能关闭spring容器的。原因是junit测试方法执行完毕进程就结束了。所以导致spring容器不能正常关闭。 正常关闭容器的方案 方案一 容器使用完手动调用close方法进行关闭。 如 //获取容器 AnnotationConfigApplicationContext ctx new AnnotationConfigApplicationContext(ApplicationConfig.class // 关闭容器 ctx.close();方案二使用java1.7的新特性try()来进行关闭。 如 try (AnnotationConfigApplicationContext ctx new AnnotationConfigApplicationContext(ApplicationConfig.class)) {SomeBean someBean ctx.getBean(SomeBean.class);System.out.println(someBean); } catch (Exception e) {e.printStackTrace(); }方案三使用Spring整合的junit单元测试。 如 在测试类上面添加整合单元测试的注解. 注意因为不再是加载配置文件的方式所以需要使用classes属性加载配置类信息。 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes ApplicationConfig.class)Scope注解 Scope 该注解贴方法上表示是多例还是单例, 相当于配置文件中bean标签的属性scope 的作用。 Scope(prototype) 表示多例 Scope(singleton) 表示单例如果配置Scope标签其默认值也是单例。一般开发中中使用的是单例。 在DI中 需求二把一个Bean注入给另外一个Bean中 方式一直接调用方法的形式 Beanpublic SomeBean someBean() {SomeBean someBean new SomeBean();System.out.println(someBean create);someBean.setOtherBean(otherBean());return someBean;}Beanpublic OtherBean otherBean() {OtherBean otherBean new OtherBean();System.out.println(otherBean create);return otherBean;}方式二使用传参的形式 Bean public SomeBean someBean(OtherBean otherBean){someBean.setOtherBean(otherBean);return someBean; }Bean public OtherBean otherBean(){return new OtherBean(); }注意 Bean标签的生命周期 在一个Configuration类中重复调用一个方法得到的对象默认也是singleton的配置类/文件的导入 为何需要导入配置类/配置文件 在我们实际开发中项目很大的情况下采用JavaConfig配置类的方式为了便于开发和管理我们的配置类也会有很多个。那么多个配置类之间只有一个主配置类这时就需要把其他的配置类或者配置文件导入到主配置类上面。所以我们需要导入配置类或者配置文件。 导入配置类/配置文件需要哪些注解 Import注解 比如一个场景我们之前项目中可以有多个 配置文件那么在javaConfig中也可能存在多个配置类那么在很多个配置类的情况下应该有一个主配置类其他的配置都关联到主配置类上面那么问题是怎么关联其他配置类呢 使用Import注解 ImportResource注解 比如一个场景有时候根据项目的需求和对项目的设计我们可能需要配置类和配置文件混用的情况。例如使用spring的AOP帮我们处理事务。可能使用javaConfig的方式比较繁琐修改代码太过于频繁那么这块我们就可以继续使用xml文件的方式统一处理。那么这种情形就需要在主配置类中关联配置文件了。 Import注解的用法 导入普通类 例子如下 新建一个TestA public class TestA {public void fun(String str) {System.out.println(str); } public void printName() {System.out.println(类名 Thread.currentThread().getStackTrace()[1].getClassName());} }新建一个ImportConfig,在类上面加上Configuration加上Configuration是为了能让Spring 扫描到这个类并且直接通过Import引入TestA类 Import({TestA.class}) Configuration public class ImportConfig { }导入带有Configuration的配置类 新建TestB Configuration public class TestB {public void fun(String str) {System.out.println(str);}public void printName() {System.out.println(类名 Thread.currentThread().getStackTrace()[1].getClassName());} } 在ImportConfig.class里面直接引入TestB Import({TestA.class,TestB.class}) Configuration public class ImportConfig { } 通过ImportSelector 方式导入的类 新建TestC.class public class TestC {public void fun(String str) {System.out.println(str);}public void printName() {System.out.println(类名 Thread.currentThread().getStackTrace()[1].getClassName());} }新建SelfImportSelector.class 实现ImportSelector 接口,注入TestC.class public class SelfImportSelector implements ImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{com.test.importdemo.TestC};} }ImportConfig上面引入SelfImportSelector.class Import({TestA.class,TestB.class,SelfImportSelector.class}) Configuration public class ImportConfig {}通过 ImportBeanDefinitionRegistrar 方式导入的类 新建TestD.class public class TestD {public void fun(String str) {System.out.println(str);} public void printName() {System.out.println(类名 Thread.currentThread().getStackTrace()[1].getClassName());} }新建SelfImportBeanDefinitionRegistrar.class,实现接口ImportBeanDefinitionRegistrar,注入TestD.class public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {RootBeanDefinition root new RootBeanDefinition(TestD.class);registry.registerBeanDefinition(testD, root);} }ImportConfig类上加上导入SelfImportBeanDefinitionRegistrar.class Import({TestA.class,TestB.class,SelfImportSelector.class,SelfImportBeanDefinitionRegistrar.class}) Configuration public class ImportConfig { }ImportResource注解的用法: 有时候根据项目的需求和对项目的设计我们可能需要配置类和配置文件混用的情况。 比如使用spring的AOP帮我们处理事务。可能使用javaConfig的方式比较繁琐修改代码太过于频繁那么这块我们就可以继续使用xml文件的方式统一处理。那么这种情形就需要在主配置类中关联配置文件了。 使用ImportResource注解 是引入spring配置文件.xml实现xml配置的装载 通过locations属性或者value属性加载对应的xml配置文件同时需要配合Configuration注解一起使用定义为配置类引入的配置类必须在启动类中扫描到. 例子如下 ApplicationConfig: Configuration ImportResource(classpath:cn/wolfcode/javaconfig/_07_import_resource/applicationContext.xml) public class ApplicationConfig {Beanpublic SomeBean someBean(){return new SomeBean();} } applicationContext.xml: ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd bean classcn.wolfcode.javaconfig._07_import_resource.OtherBean/ /beans ImportResourceConfigTest: RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes ApplicationConfig.class) public class ImportResourceConfigTest {Autowiredprivate SomeBean someBean;Autowiredprivate OtherBean otherBean;Testpublic void testImportResource() throws Exception {System.out.println(someBean someBean);System.out.println(otherBean otherBean);} }资源文件的导入 为何需要导入资源文件 Spring Boot 官网使用的是application.properties文件来实现文件的配置。但是实际情况下一个配置文件是不够用的比如项目集成redismq以及数据库比如mysql的时候多个配置文件有利于开发及维护的管理。 导入资源文件需要学习哪些注解 PropertySource注解 大多数情况项目需要配置的内容会比较复杂这时候需要使用多个文件进行配置 PropertySource是Spring boot为了方便引入properties配置文件提供的一个注解可以标注在SpringBoot的启动类上还可以标注在配置类使用Configuration标注的类上。 Value注解 Value用于将外部的值动态地注入Bean中相当于使用.xml中的如下的代码。通常用于对某个值进行单个的注入毕竟如果对整个Bean内的值进行注入我们有更好用的ConfigurtionProperties可以使用。 ConfigurtionProperties注解 Value通常用于对某个位置获取配置文件中的的某一个变量的时候而ConfigurationProperties用于javaBean和配置文件进行整体映射。上述的使用场景只是说通常情况具体的使用还是要根据Value和ConfigurationProperties各自的特点来进行判断。 Value主要作用到变量上而ConfigurationProperties主要用于方法。 PropertySource注解的用法 加载指定的属性文件 注解的属性value是一个String数组内容为一个或多个xml/properties文件的路径相对于classpath 注解内部的属性使用配合value注解. properties属性文件是key-value格式的因此使用起来 是采用value(${key}); 这种形式 如 Configuration PropertySource(value classpath:db.properties, ignoreResourceNotFound false , encoding utf-8) public class ApplicationConfig { }属性value value值是设置需要加载的属性文件可以一次性加载多个。 属性encoding encoding用于指定读取属性文件所使用的编码我们通常使用的是UTF-8 属性ignoreResourceNotFound ignoreResourceNotFound含义是当指定的配置文件不存在是否报错默认是false;实际项目开发中最好设置为false。 Environment对象的使用 回想mybaits配置文件中的 Environment 表示mybatis的当前环境 Environment 代表了spring的当前环境在该环境中只有两个东西 1外部读入的资源文件 如通过PropertySource 引入的资源文件2还有一个东西叫 profile那么在javaconfig中如何使用 Environment 实现资源文件的注入呢 ? Autowired private Environment evn;Configuration //PropertySource:把资源文件导入到Spring当前环境 PropertySource(classpath:jdbc.properties) public class ApplicationConfig { // Environment spring的环境对象其中有两个东西① propertis ② profileBean public MyDataSource myDataSource(Environment environment){return new MyDataSource(environment.getProperty(jdbc.username),environment.getProperty(jdbc.password),environment.getProperty(jdbc.driverClassName),environment.getProperty(jdbc.url));} } Value注解的用法 我们可以点进去看一下Value的源码如下我们发现它其中只包括一个String类型的变量也就是说我们Value注解后面只能接一个String类型的变量无论什么内容都必须包括在双引号之下。 可注入类型 字面量包括布尔、数值型、字符串a. 字符串 Value(字符串内容) 适用于一般的自变量、数组、文件资源和URL资源Spring Boot会根据配置的变量类型对字符串内容进行转换。 例如 Value(true) private Boolean blog; b. SpEL Value(#{SpEL内容})。 通常SpEL内的字符串使用单引号括起来。适用于需要计算的自变量、特殊数组、键值对、其他bean属性等。 例如Value(#{12*15}) private Integer clickNum; c. 注入配置文件中的数据 Configuration PropertySource(classpath:jdbc.properties) public class ApplicationConfig {//取资源文件中的内容对于的值设置到该字段上Value(${jdbc.username})private String username;Value(${jdbc.driverClassName})private String driverClassName;Value(${jdbc.url})private String url;Value(${jdbc.password})private String password;Beanpublic MyDataSource myDataSource(){return new MyDataSource(username,password,driverClassName,url); } 注意 如果spring的jar版本过低必须配置PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer 完成资源文件属性到对象参数的绑定,从spring环境对象中拿到资源文件配置,完成对 {key} 表达式的替换 Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){return new PropertySourcesPlaceholderConfigurer();} }PropertySourcesPlaceholderConfigurer 类最终实现了一个 BeanFactoryPostProcessor 接口 他的作用是在BeanFactory创建每一个bean的过程当中加入一些自己的业务逻辑 而实现了BeanFactoryPostProcessor 接口的bean 会在其他所有bean 初始化之前去做一些事情 而 PropertySourcesPlaceholderConfigurer 就是在其他所有的bean初始化之前去寻找是否有 value 标签, 如果有完成属性的替换, 所以我们得需要保证 PropertySourcesPlaceholderConfigurer 在其他所有类之前被创建,所以需要在 该bean的定义方法是 static 数组List 字符串与字面量类似字符串之间使用英文的“,”隔开。 如 Value(Spring Boot, IDEA) private ListString key;SpEL比如我们需要字符串中有逗号的时候使用SpEL就会更合适一些。 如 Value(#{Spring Boot;IDEA.split(;)}) private ListString key;键值对Map 对于键值对我们不能直接使用字符串可以使用SpEL也可以配合配置文件来进行使用。 a. SpEL注意第二层的括号一定要有 Value(#{{color:red, language:Chinese}}) private MapString,String otherProperties;b. 如果结合配置文件使用我们这里使用.properties格式和.yml格式的配置的方式有些不同先来看.properties配置文件代码 valuesMap{color:red, language:Chinese}代码中获取Value(#{${valuesMap}})private MapString,String otherProperties;如果配置文件使用yml需要注意。 yml在进行单行键值对赋值的时候使用{}所以需要加上双引号因为单引号会将字符串内容转义所以我们这里使用双引号。.yml配置文件代码 valuesMap: {color:red, language:Chinese} 代码中获取 Value(#{${valuesMap}}) private MapString,String otherProperties;注入其它bean属性 otherBean是一个Bean对象name是它的一个属性可以通过Value(“#{otherBean.name}”)将这个bean的属性注入Value声明的属性里 Value(#{otherBean.name}) private String someName;URL资源 与字面量中的字符串类型变量的注入差不多支持多种形式我们只示例字符串的形式 如 Value(http://www.baidu.com) private Resource address;操作系统属性 操作系统的属性是静态全局变量systemEnvironment存入可通过它获取到操作系统的属性。 Value(#{systemProperties[os.name]}) private String name;文件资源 与字面量中的字符串类型变量的注入差不多支持多种形式我们只示例一种。注意这里我们一定要在文件路径前面加上classpath并且将路径从文件夹处复制过来的时候最好更改格式把里面的“\”和“\”改为“/”。当然你也可以不改Spring Boot也能够识别 如 Value(classpath:D:/code/application/a.txt)private Resource intro;开发环境的切换 为何需要学习Profile注解 由于我们平时在开发中通常会出现在开发的时候使用一个开发数据库测试的时候使用一个测试的数据库而实际部署的时候需要一个数据库。以前的做法是将这些信息写在一个配置文件中当我把代码部署到测试的环境中将配置文件改成测试环境当测试完成项目需要部署到现在了又要将配置信息改成现在的。非常麻烦。 而使用了Profile之后我们就可以分别定义3个配置文件一个用于开发、一个用户测试、一个用户生产其分别对应于3个Profile。当在实际运行的时候只需给定一个参数来激活对应的Profile即可那么容器就会只加载激活后的配置文件这样就可以大大省去我们修改配置信息而带来的烦恼。 Profile/ActiveProfile注解 spring3.1开始引入,一般用于多环境配置 Profile注解用于实现通过修改运行时参数切换不同的开发环境 Profile注解可以加在类上也可以加载注入bean的方法上 Profile只有一个默认的java.lang.String[]类型的属性value因此它可以指定一个或多个配置名。 Profile注解匹配的名字才会去处理没有匹配的则会被抛弃。 Profile标签能够定义不同的运行环境在测试的时候可以通过 ActiveProfile来指定运行环境 如何使用两个注解完成环境的切换 1.png 开发环境配置 Configuration PropertySource(classpath:dev.properties) Profile(dev) public class ApplicationDevConfig { Bean public MyDataSource myDataSource(Environment environment){return new MyDataSource(environment.getProperty(jdbc.username) ,environment.getProperty(jdbc.password) ,environment.getProperty(jdbc.driverClassName) ,environment.getProperty(jdbc.url));} }测试环境配置 Configuration PropertySource(classpath:test.properties) Profile(test) public class ApplicationTestConfig {Beanpublic MyDataSource myDataSource(Environment environment){return new MyDataSource(environment.getProperty(jdbc.username) ,environment.getProperty(jdbc.password),environment.getProperty(jdbc.driverClassName),environment.getProperty(jdbc.url));} }主配置 Configuration Import({ApplicationDevConfig.class,ApplicationTestConfig.class}) public class ApplicationConfig { }测试 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes ApplicationConfig.class) ActiveProfiles(test) public class JavaConfigTest {Autowiredprivate MyDataSource myDataSource;Testpublic void someBeanTest(){ System.out.println(myDataSource.toString());} }HelloWorld案例 第一个helloWorld案例 pom.xml: parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.0.5.RELEASE/versionrelativePath/ /parent!--整合web--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency HelloWordController: Controller SpringBootApplication public class HelloWordController {RequestMapping(/helloboot)ResponseBodypublic String hello() {System.out.println(hello springBoot);return hello springBoot;}public static void main(String[] args) {SpringApplication.run(HelloWordController.class,args);} }运行原理分析 1使用 parent 继承spring-boot-starter-parent引入基本的依赖管理配置 2引入spring-boot-starter-web自动引入了springweb相关的包 SpringBootApplication 标签做了哪些事情 SpringBootApplication由三个主要的标签构成SpringBootConfigurationEnableAutoConfigurationComponentScan 1SpringBootConfiguration本质就是一个Configuration代表这是spring容器的主配置类 2EnableAutoConfiguration开启自动配置Springboot使用这个标签自动的把内置的符合条件的Configuration类加载进入应用 可以查看spring-boot-autoconfigure包中的META-INF/spring.factories文件中的配置项原理由EnableAutoConfiguration标签引入的AutoConfigurationImportSelector类中使用Spring的SpringFactoriesLoader类实现加载 3ComponentScan自动扫描 总结一句话 SpringBootApplication这个注解告诉springboot自动的去完成相关配置包括基础类的加载bean的扫描等等这个后面详细介绍简单理解为这个标签为我们的应用配置完成了很多基本功能 SpringApplication.run 又做了哪些事情 读取配置对象,配置相关自动配置对象,启动tomcat加载应用 总结一句话 SpringApplication.run这个是springboot为我们提供的最大的区别在于springboot不再是一个web应用需要我们自己去打包部署启动tomcatspringboot默认把tomcat打包到应用中我们可以以正常的运行jar的方式来运行springboot应用 springBoot项目独立运行方式 注意默认的Maven打包方式是不能正常的打包SpringBoot项目的,需要额外的引入打包插件,才能正常的对SpringBoot项目 打成jar包,以后只要拿到该jar包就能脱离IDE工具独立运行了使用插件 springboot:run 添加插件 buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build 对于eclipse 项目要打包,引入插件之后 直接用 package 命令、 对于idea直接点击打包插件即可打包独立运行 执行java -jar xxx.jar 运行(在字节码编译目录中会有打包好的 jar) 使用main方法启动 方式一直接调用run方法 SpringApplication.run(StartModeController.class,args);方式二可以通过创建对象的方式来运行SpringApplication SpringApplication application new SpringApplication(StartModeController.class); application.run(args);方式三通过builder完成 SpringApplication application new SpringApplicationBuilder(StartModeController.class).build();application.run(args);Springboot的优缺点 创建独立的Spring应用程序嵌入的Tomcat无需部署WAR文件简化Maven配置自动配置Spring提供生产就绪型功能如日志健康检查和外部配置XML没有要求配置非常容易和第三方框架集成起来 缺点 1版本更新较快可能出现较大变化 2因为约定大于配置所以经常会出现一些很难解决的问题 Springboot基本使用 应用构建 使用官网进行构建springboot项目 构建项目的地址http://start.spring.io/使用开发工具构建springboot项目 新建一个项目 选则 spring Initializr 选项。 填写相关的信息。选则相关的jar依赖。热部署 直接添加 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactIdoptionaltrue/optional /dependency 即可 可以在application.properties文件中设置一些属性 #默认排除的资源 spring.devtools.restart.excludestatic/**,templates/**,public/** #增加额外的排除资源 spring.devtools.restart.additional-excludepublic/** #处理默认配置排除之外的 spring.devtools.restart.enabledfalse #禁用自动重启 热部署的原理 SpringBoot重启是restart重启通过监控classpath的变化如果classpath中的文件发生变化即出发重启。springboot通过两个classpath来完成reload一个basic classloader中加载不变的类一个restart classloader中加载classpath中的类重启的时候restart classloader中的类丢弃并重新加载所以 设置自动编译如果您觉得 SpringBoot的热部署不怎么好用那你也可以去掉热部署的依赖使用自动编译 1开启自动编译 :setting - Build... - compiler - Build project automatically 2ctrl alt shift / - registry - compiler.automake.allow.when.app.running 设置banner 1可以直接在classpath下添加一个banner.txt文件即可 2介绍springboot的配置文件。springboot默认在classpath中通过application.properties文件来进行配置比如 spring.main.banner-modeoff 就可以关闭banner输出 SpringApplication的参数 可以通过注入一个ApplicationArguments对象来完成参数的封装 Autowired private ApplicationArguments args;RequestMapping(/args)public String args() {return args.getNonOptionArgs().toString(); }Springboot开发WEB应用 集成日志框架 为什么要用日志 1比起System.out.println日志框架可以把日志的输出和代码分离 2日志框架可以方便的定义日志的输出环境控制台文件数据库 3日志框架可以方便的定义日志的输出格式和输出级别java常用日志框架类别介绍 Log4j Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。 Log4j 2 Apache Log4j 2是apache开发的一款Log4j的升级产品。 Commons Logging Apache基金会所属的项目是一套Java日志接口之前叫Jakarta Commons Logging后更名为Commons Logging。 Slf4j 类似于Commons Logging是一套简易Java日志门面本身并无日志的实现。Simple Logging Facade for Java缩写Slf4j。 Logback 一套日志组件的实现(slf4j阵营)。 Java常用日志框架历史 1996年早期欧洲安全电子市场项目组决定编写它自己的程序跟踪API(Tracing API)。经过不断的完善这个API终于成为一个十分受欢迎的Java日志软件包即Log4j。后来Log4j成为Apache基金会项目中的一员。 期间Log4j近乎成了Java社区的日志标准。据说Apache基金会还曾经建议sun引入Log4j到java的标准库中但Sun拒绝了。 2002年Java1.4发布Sun推出了自己的日志库JUL(Java Util Logging),其实现基本模仿了Log4j的实现。在JUL出来以前log4j就已经成为一项成熟的技术使得log4j在选择上占据了一定的优势。 接着Apache推出了Jakarta Commons LoggingJCL只是定义了一套日志接口(其内部也提供一个Simple Log的简单实现)支持运行时动态加载日志组件的实现也就是说在你应用代码里只需调用Commons Logging的接口底层实现可以是log4j也可以是Java Util Logging。 后来(2006年)Ceki Gülcü不适应Apache的工作方式离开了Apache。然后先后创建了slf4j(日志门面接口类似于Commons Logging)和Logback(Slf4j的实现)两个项目并回瑞典创建了QOS公司QOS官网上是这样描述Logback的The GenericReliable FastFlexible Logging Framework(一个通用可靠快速且灵活的日志框架)。 Apache眼看有被Logback反超的势头于2012-07重写了log4j 1.x成立了新的项目Log4j 2。Log4j 2具有logback的所有特性。Log4j2与Log4j1发生了很大的变化log4j2不兼容log4j1。 Springboot的默认日志使用 1Springboot默认已经开启日志默认的日志格式为时间 日志级别 PID 线程名称 日志类 日志说明 2Springboot的日志区别系统日志和应用日志 3Springboot推荐使用Logback作为日志框架 Logback使用方法推荐使用logback自己的配置文件 1springboot默认支持logback.xml或者logback-spring.xml推荐使用logback-spring.xmlspringboot会增加额外功能 2可以通过logging.configclasspath:mylogback.xml指定自己的logback配置文件不推荐 3一个典型的logback配置文件 Logback使用介绍 使用日志框架的步骤 a. 在resources文件夹下面创建一个xml文件文件的名称使用 logback-spring.xml。 b. 在logback-spring.xml文件中编写日志文件的内容 ?xml version1.0 encodingutf-8 ? configuration!--日志的输出方式 输出到控制台--appender nameSTDOUT classch.qos.logback.core.ConsoleAppenderencoderpattern%d{yyyy-MM-dd-HH:mm:ss.SSS} %level [%thread]-%class:%line%msg%n/pattern/encoder/appender!--配置日志的类型以及输出日志的级别 使用系统的日志 日志级别为info--root levelinfo!--必须要和appender中的name属性的值保持一致--appender-ref refSTDOUT//root /configuration c.启动项目即可。 参考日志格式: %d{yyyy-MM-dd-HH:mm:ss} %level [%thread]-%class:%line %msg %n格式中的标识符组成: %logger{n}: 输出Logger对象类名,n代表长度 %class{n}: 输出所在类名 %d{pattern}或者date{pattern}: 输出日志日期,格式同java %L/line: 日志所在行号 %m/msg: 日志内容 %method: 所在方法名称 %p/level: 日志级别 %thread: 所在线程名称关于logback-spring.xml配置文件的详细解析 1configuration:Logback配置根元素 属性包括 a,scan: 当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true。b,scanPeriod: 设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。c,debug: 当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。子元素 contextName上下文名字 property:定义属性可以使用${}在配置文件中使用2appender在logback中是用于具体记录日志的组件可以用来配置日志记录方式日志记录格式等 属性包括 name:appender的名字用于下面在配置日志的时候指定 class:使用到的appender类常见的appender 1ch.qos.logback.core.ConsoleAppender:输出到控制台 !--输出到控制台-- appender nameSTDOUT classch.qos.logback.core.ConsoleAppender !--日志格式化--encoderpattern%d{yyyy-MM-dd-HH:mm:ss.SSS} %level [%thread]-%class:%line%msg%n/pattern/encoder /appender2ch.qos.logback.core.FileAppender输出到文件 file被写入的文件名可以是相对目录也可以是绝对目录如果上级目录不存在会自动创建没有默认值。 append文件结尾如果是 false清空现存文件默认是true。 encoder对日志进行格式化 !--输出到文件中-- appender nameFILE classch.qos.logback.core.FileAppenderencoderpattern%d{yyyy-MM-dd-HH:mm:ss.SSS} %level [%thread]-%class:%line%msg%n/pattern/encoderappendfalse/appendfilemylog.log/file /appender3ch.qos.logback.core.rolling.RollingFileAppender输出到文件可以配置滚动策略当日志达到某个条件之后分文件记录 append如果是 true日志被追加到文件结尾如果是 false清空现存文件默认是true。 rollingPolicy:滚动策略涉及文件移动和重命名。常用滚动策略 ch.qos.logback.core.rolling.TimeBasedRollingPolicy按照时间控制来控制记录文件 fileNamePattern文件名称格式以%d{pattern} maxHistory: 可选节点控制保留的归档文件的最大数量超出数量就删除旧文件。以文件最小时间为准!--输出到文件可以设置文件滚动分割条件按照时间分割-- appender nameRollingTimeFile classch.qos.logback.core.rolling.RollingFileAppenderencoderpattern%d{yyyy-MM-dd-HH:mm:ss.SSS} %level [%thread]-%class:%line%msg%n/pattern/encoderrollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicyfileNamePatternmylog.%d{yyyy-MM-dd}.log/fileNamePatternmaxHistory30/maxHistory/rollingPolicy /appenderch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy:按照时间和大小控制记录文件 fileNamePattern文件名称格式可以使用%i来控制索引编号 maxFileSize这是活动文件的大小默认值是10MB maxHistory:可选节点控制保留的归档文件的最大数量超出数量就删除旧文件。以文件最小时间为准!--输出到文件可以设置文件滚动分割条件按照文件大小分割-- appender nameRollingSizeFile classch.qos.logback.core.rolling.RollingFileAppenderencoderpattern%d{yyyy-MM-dd-HH:mm:ss.SSS} %level [%thread]-%class:%line%msg%n/pattern/encoderrollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicyfileNamePatternmylog.%d{yyyy-MM-dd}.%i.log/fileNamePatternmaxFileSize1kb/maxFileSizemaxHistory30/maxHistory/rollingPolicy /appenderlogger元素用来设置某一个包或具体的某一个类的日志打印级别及对应的appender 属性 name: 用来指定受此loger约束的某一个包或者具体的某一个类子节点 appender-ref可以配置多个标识这个appender将会添加到这个logger如 !--使用自己的日志-- logger leveltrace namecn.wolfcode.springbootappender-ref refSTDOUT/ /loggerroot元素特殊的logger代表根配置如果没有单独指定日志包层级都默认使用root定义的日志输出级别 属性 level指定日志级别如 !--使用系统的日志-- root levelinfoappender-ref refSTDOUT/ /root在代码中可以使用自定义的Logger对象输出日志信息。 实现的方式一通过LoggerFactory工厂对象创建Logger对象 // 方式一自己定义一个Logger对象private static final Logger LOGGER LoggerFactory.getLogger(LogController.class);RequestMapping(/log)ResponseBodypublic String log() {// 方式一的出生日志的方式LOGGER.info(方式一我是info);LOGGER.debug(方式一我是debug);LOGGER.error(方式一我是error);return log;} 实现的方式二使用注解的方式 Slf4j // 方式二使用注解来输出日志前提是需要依赖lombok包 public class LogController {RequestMapping(/log)ResponseBodypublic String log() {// 方式二的输出方式log.trace(方式二 trace信息);log.debug(方式二 debug信息);log.info(方式二 info{}信息, 33333);log.error(方式二 error信息);return log;}SpringBoot项目的目录结构 我们通过idea创建出来的SpringBoot项目会生成一个标准的项目的目录结构。 2.png application.properties优先级 一个项目中可以有多个application.properties文件存放在不同目录中,此时他们会遵循固定的优先级来处理有冲突的属性配置 项目/config/application.properties项目/application.propertiesclasspath:config/application.propertiesclasspath:application.properties 一般都在classpath:application.properties做配置,其他方式不使用 静态资源 默认情况下,Springboot会从classpath下的 /static , /public , /resources , /META-INF/resources下加载静态资源可以在application.properties中配置spring.resources.staticLocations属性来修改静态资源加载地址 spring.resources.static-locationsclasspath:/hello 注意设置完以后会覆盖之前的设置。 因为应用是打成jar包,所以之前的src/main/webapp就作废了,如果有文件上传,那么就的必须去配置图片所在的路径 spring.resources.static-locationsclasspath:/static,file:///Users/tony/Desktop/image/ 集成Freemarker 为何要集成Freemarker 1.性能。velocity应该是最好的其次是jsp普通的页面freemarker性能最差虽然只是几毫秒到十几毫秒的差距。但是在复杂页面上包含大量判断、日期金额格式化的页面上freemarker的性能比使用tag和el的jsp好。 2、宏定义比jsp tag方便 3、内置大量常用功能。比如html过滤日期金额格式化等等使用非常方便 4、支持jsp标签 5、可以实现严格的mvc分离 6、易学易用 我是看了一天文档就用得挺熟练了freemarker文档写得太好了例子丰富照做一遍全都会了。 7、功能强大 比Velocity强大多了还支持JSP Tag。不过最有意义的是macro功能可以自定义常用的macro实现页面常规操作的可复用性。 8、报错信息友好 很多应用服务器的JSP报错信息是无法定位到源代码行的。不过freemarker报错定位很准确丝毫不差而且信息丰富一看就知道怎么回事(虽然那个黄黄的页面看起来让人难受) 与JSP相比FreeMarker的一个优点在于不能轻易突破模板语言开始编写Java代码因此降低了领域逻辑漏进视图层的危险几率。但缺点是需要一点附加配置来将其平稳地集成到应用程序中一些IDE集成开发环境可能并不完全支持它当然还有开发者或设计者也许需要学习一门陌生的模板语言。相关的JAR文件将要添加到WEB-INF/lib在需要的时候它们包含在Spring中 。 Freemarker的一些常见语法回顾 获取当前日期必须要格式化显示 input value${.now?string(yyyy-MM-dd)}/获取Controller控制器中共享给页面的对象中的普通属性 input id${user.name} name${user.name} value${user.name}/ 获取Controller控制器中共享给页面的对象中的日期类型属性必须要格式化显示 input value${(user.birthday?string(yyyy-MM-dd))!}/获取Controller控制器中共享给页面的对象中的boolean类型属性必须要处理显示 input value${user.active?string(是,否)} 对null 或者不存在的对象进行取值可以设置默认值 例${var!我是默认值} 即有值时显示正常值无值时显示默认值 如果需要判断使用if标签判断 #--判断是否小于25-- #if user.age 25 young #elseold /#if br/ #--判断是否大于25-- #if user.age gt; 25 old #elseyoung /#if 如果需要判断可以使用switch标签判断 #switch user.age#case 30very old#break #case 25old#break #default young#break /#switch 获取Controller控制器中共享给页面的list集合必须要遍历进行显示 #list userList as persontrtd${person.name}/tdtd${(person.age25) ?string(old,young)}/tdtd${(person.birthday?string(yyyy-MM-dd hh:mm:ss))!}/tdtd${person.active?string(是,否)}/td/tr /#list userList 这个名字必须和controller控制器中的共享的key保持一致。 获取Controller控制器中共享给页面的map集合必须要遍历进行显示 #list map?keys as key${key}:${map[key]}br/ /#listmap 这个名字必须和controller控制器中的共享的key保持一致。 自定义变量 #assign num 100 / 自定义的变量参与计算 font colorred ${num * 10} /fontbr 处理list集合 first: 取List值第一个值br/ span${userList?first}/spanlast: 取List值最后一个值br/ span${userList?last}/spansize: 集合大小br/ span${userList?size}/spansort: 对集合进行排序br/ #list userList?sort as item span${item.name}/span /#list br/如何集成Freemarker 导入相关的依赖 !--整合freemarker--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-freemarker/artifactId/dependency在resources/templates目录下面创建对应的freemarker模板。 freemarker.ftl: !DOCTYPE html html langen headmeta charsetUTF-8title/title /head body tabletrth姓名/thth年龄/thth备注/thth生日/thth是否激活/th/tr#list userList as persontrtd${person.name}/tdtd${person.age}/tdtd${(person.age25) ?string(old,young)}/tdtd${(person.birthday?string(yyyy-MM-dd hh:mm:ss))!} /tdtd${person.active?string(是,否)}/td/tr/#list/body /table 编写相应的Controller FreemarkerController: Controller RequestMapping(/freemarker) public class FreemarkerController {RequestMapping(/hello)public String hello(ModelMap map) {User u new User();u.setName(haozz);u.setAge(24);u.setPassword(qwerty);u.setBirthday(new Date());u.setBirthday(null);u.setActive(false);User u1 new User();u1.setName(nico robin);u1.setAge(35);u1.setPassword(qwerty);u1.setBirthday(new Date());u1.setActive(true);ListUser userList new ArrayList();userList.add(u);userList.add(u1);map.addAttribute(userList,userList);return freemarker; } 集成原理 SpringBoot的自动配置中含有FreeMarkerAutoConfiguration配置对象,该配置对象又导入了 FreeMarkerReactiveWebConfiguration配置对象,在里面创建了FreeMarkerConfigurer和FreeMarkerViewResolve 两个对象交给Spring管理,并且设置了默认的属性值,这些属性值来源于FreeMarkerProperties对象 常见的属性配置 spring.freemarker.enabledtrue: 是否开启freemarker支持spring.freemarker.allow-request-override: 是否允许request中的属性覆盖model中同名属性,默认false spring.freemarker.allow-session-override: 是否允许session中的属性覆盖model中同名属性,默认false spring.freemarker.cache: 是否支持模板缓存,默认falsespring.freemarker.charsetUTF-8: 模板编码spring.freemarker.content-typetext/html: 模板contenttype spring.freemarker.expose-request-attributes: 是否开启request属性暴露,默认falsespring.freemarker.expose-session-attributes: 是否开启session属性暴露,默认false spring.freemarker.expose-spring-macro-helpers: 是否开启spring的freemarker宏支持,默认为false spring.freemarker.prefer-file-system-access: 默认为true,支持实时检查模板修改 spring.freemarker.prefix: 加载模板时候的前缀spring.freemarker.settings.*: 直接配置freemarker参数spring.freemarker.suffix: 模板文件后缀 spring.freemarker.template-loader-pathclasspath:/templates/: 模板加载地址 集成Thymeleaf 为何要集成Thymeleaf Thymeleaf是个XML/XHTML/HTML5模板引擎可以用于Web与非Web应用。 Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码开发者只需将标签属性添加到模板中即可。接下来这些标签属性就会在DOM文档对象模型上执行预先制定好的逻辑。Thymeleaf的可扩展性也非常棒。你可以使用它定义自己的模板属性集合这样就可以计算自定义表达式并使用自定义逻辑。这意味着Thymeleaf还可以作为模板引擎框架。 thymeleaf优点静态html嵌入标签属性浏览器可以直接打开模板文件便于前后端联调。 Thymeleaf模板引擎是springboot中默认配置与freemarker相似可以完全取代jsp在springboot中它的默认路径是src/main/resources/templates 静态文件css, js 等文件默认路径是src/main/resources/static所有项目中如果没有这个目录需要手动加上了 Thymeleaf的一些常见语法回顾 获取Controller控制器中共享给页面的对象中的普通属性 input th:value${user.age}/获取Controller控制器中共享给页面的对象中的日期类型属性 input th:value${#dates.format(user.birthday,yyyy-MM-dd)}/获取Controller控制器中共享给页面的对象中的boolean类型属性 td th:text${person.flag}/td获取Controller控制器中共享给页面的list集合必须要遍历进行显示 tr th:eachperson:${userList}td th:text${person.name}/tdtd th:text${person.age ge 25} ? old : young/tdtd th:text${#dates.format(person.birthday,yyyy-MM-dd hh:mm:ss)}/tdtd th:text${person.flag}/td /tr如果需要判断使用if标签判断 div th:if${user.age lt 25}young/div如果需要判断可以使用switch标签判断 div th:switch${user.name}p th:casehaozz最帅的/pp th:casenico robin妮可罗宾/pp th:casenami娜美/p /div处理表单(action跳转地址method设置请求方式object抽取相同的部分) form th:action{/th/postform} th:object${user} th:methodpost !--th:field*{name}相当于idname namename value具体的name值-- input typetext th:field*{name}/ input typesubmit/ /form处理html内容被解析转译 span th:utext${user.desc}/span th:utext 会进行转译br/ th:text 不会进行转译br/常见的th标签汇总 th标签汇总图.png 如何集成Thymeleaf 导入相关的依赖。 !--整合thymeleaf-- dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId /dependency在resources/templates目录下面创建对应的thymeleaf模板。 !DOCTYPE html html langen xmlns:thhttp://www.w3.org/1999/xhtml xmlns:methodhttp://www.w3.org/1999/xhtml headmeta charsetUTF-8titleTitle/title /head body tabletrth姓名/thth年龄/thth备注/thth生日/thth婚否/th/trtr th:eachperson:${userList}td th:text${person.name}/tdtd th:text${person.age}/tdtd th:text${person.age ge 25} ? old : young/tdtd th:text${#dates.format(person.birthday,yyyy-MM-dd hh:mm:ss)}/tdtd th:text${person.active}/td/tr /table /body /html 编写相应的Controller Controller RequestMapping(/freemarker) public class FreemarkerController {RequestMapping(/hello)public String hello(ModelMap map) {User u new User();u.setName(haozz);u.setAge(24);u.setPassword(qwerty);u.setBirthday(new Date());u.setBirthday(null);u.setActive(false);User u1 new User();u1.setName(nico robin);u1.setAge(35);u1.setPassword(qwerty);u1.setBirthday(new Date());u1.setActive(true);ListUser userList new ArrayList();userList.add(u);userList.add(u1);map.addAttribute(userList,userList);return freemarker; } 集成原理 SpringBoot的自动配置中含有ThymeleafAutoConfiguration配置对象,该配置对象的里面创建了视图解析器ThymeleafViewResolver和模板引擎 SpringTemplateEngine 和模板解析器SpringResourceTemplateResolver 三个对象交给Spring管理,并且设置了默认的属性值,这些属性值来源于ThymeleafProperties对象 常见属性设置 spring.thymeleaf.prefixclasspath:/templates/ 设置thymeleaf路径默认为src/main/resources/templates spring.thymeleaf.suffix.html 设置thymeleaf模板后缀 spring.thymeleaf.content-typetext/html spring.thymeleaf.cachefalse 是否开启缓存默认为true spring.thymeleaf.modeLEGACYHTML5 设置thymeleaf严格校验 spring.thymeleaf.encodingUTF-8 设置编码 了解ConfigurtionProperties注解的用法 属性名匹配规则 ConfigurationProperties的属性名匹配规则Relaxed bindingSpring Boot可以对下面四种类型的命名进行自动匹配也就是说配置文件和类文件中的名称不需要完全相同使用下面的任意两种系统就会将二者匹配上 标准方式变量之间通过下一个单词的首字母大写的方式隔开 egstudent.isFemale 使用“-”进行单词之间的连接 egstudent.is-female 使用“_”进行单词之间的连接 egstudent.is_female 全部大写使用“_”连接通常对系统属性变量推荐这种写法。 egSTUDENT_IS_FEMALE属性ignoreInvalidFields 标记当有非法字段绑定到这个对象时可以被忽略。非法指根据使用的binder非法通常这意味着字段类型错误(或者无法强制转为正确的类型).默认false。这意味着不能忽略字段非法所以只能报错 属性ignoreUnknownFields 标记当有未知字段绑定到这个对象时可以被忽略。未知字段可能是属性中的一个符号错误。默认true。 属性prefix/value 要绑定到这个对象的有效的属性的名字前缀。value 和 prefix 是同义词 案例如下 ConfigurationProperties(prefix spring.datasource) SetterGetterToString Repository public class MyDataSource {private String username;private String url;private String password;private String driverClassName; }application.properties:spring.datasource.driver-class-namecom.mysql.jdbc.Driver spring.datasource.urljdbc:mysql:///crm spring.datasource.usernameroot spring.datasource.passwordroot123 spring.datasource.typecom.alibaba.druid.pool.DruidDataSourceController SpringBootApplication public class DataSourcesController {Autowiredprivate MyDataSource myDataSource;RequestMapping(/source)ResponseBodypublic String hello() {return myDataSource.toString();}public static void main(String[] args) {SpringApplication.run(App.class,args);} }集成Druid连接池 为何要集成Druid 1、性能方面 hikariCPdruidtomcat-jdbcdbcpc3p0 。hikariCP的高性能得益于最大限度的避免锁竞争。 2、druid功能最为全面sql拦截等功能统计数据较为全面具有良好的扩展性。 3、综合性能扩展性等方面可考虑使用druid或者hikariCP连接池比较方便对jdbc接口进行监控跟踪等。 4、可开启prepareStatement缓存对性能会有大概20%的提升。 psCache是connection私有的所以不存在线程竞争的问题开启pscache不会存在竞争的性能损耗。 psCache的key为prepare执行的sql和catalog等value对应的为prepareStatement对象。开启缓存主要是减少了解析sql的开销。 5、3p0历史悠久代码及其复杂不利于维护。并且存在deadlock的潜在风险。 6、Druid可以打印SQL慢查询方面的日志 回顾Druid连接池在SSM框架中的用法 在pom.xml文件中导入依赖 !-- MySQL驱动 --dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.38/versionscoperuntime/scope/dependency!-- druid连接池 --dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.0.26/version/dependency!--spring jdbc--dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependency spring的主配置文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:aophttp://www.springframework.org/schema/aop xmlns:txhttp://www.springframework.org/schema/txxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd!--组件扫描器--context:component-scan base-packagecn.wolfcode.crm/!--自动DI解析器--context:annotation-config/!--加载数据库的配置信息--context:property-placeholder locationclasspath:db.properties system-properties-modeNEVER/!-- 连接池对象 --bean iddataSource classcom.alibaba.druid.pool.DruidDataSourceinit-methodinit destroy-methodcloseproperty namedriverClassName value${jdbc.driverClassName}/property nameusername value${jdbc.username}/property nameurl value${jdbc.url}/property namepassword value${jdbc.password}//bean /beans 如何集成Druid 方式一 pom.xml: !--整合DrudiDataSource--!--mysql--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependency!--druid--dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependency!--jdbc--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependency application.properties: spring.datasource.driver-class-namecom.mysql.jdbc.Driver spring.datasource.urljdbc:mysql:///crm spring.datasource.usernameroot spring.datasource.passwordroot123 spring.datasource.typecom.alibaba.druid.pool.DruidDataSource 方式二 pom.xml: !--整合DrudiDataSource--!--mysql--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependency!--druid--dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.10/version/dependency!--jdbc--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependency application.properties: spring.datasource.druid.driver-class-namecom.mysql.jdbc.Driver spring.datasource.druid.urljdbc:mysql:///crm spring.datasource.druid.usernameroot spring.datasource.druid.passwordroot123 测试案例 RestController public class DataSourceController {Autowiredprivate DataSource dataSource;RequestMapping(/dataSource)public String showData() throws SQLException {return dataSource.getConnection().toString();} } 集成原理 SpringBoot的自动配置中含有DataSourceAutoConfiguration配置对象,该配置对象含有个内部类,该内部类也是配置 类,当容器中没有连接池对象时,就会Generic方式来创建连接池对象交给Spring管理,用到是属性值来源于 DataSourceProperties对象 集成Junit框架 为何要集成Junit 我们在开发的过程中肯定需要不断的对我们自己写的代码进行测试。所以离不开Junit单元测试。 导入依赖 !--junit-- dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactId /dependency 准备配置类 public class SomBean {public SomBean() {System.out.println(构造器);} } Configuration public class JunitConfig {Beanpublic SomBean somBean(){return new SomBean();} } 编写测试类 RunWith(SpringRunner.class) SpringBootTest(classes JunitConfig.class) public class App {Autowiredprivate SomBean somBean;Testpublic void test(){System.out.println(somBean somBean);}}集成MyBatis框架 为何要集成MyBatis 1、简单易学 mybatis本身就很小且简单。没有任何第三方依赖最简单安装只要两个jar文件配置几个sql映射文件易于学习易于使用通过文档和源代码可以比较完全的掌握它的设计思路和实现。2、灵活 mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能或许更多。3、解除sql与程序代码的耦合 通过提供DAL层将业务逻辑和数据访问逻辑分离使系统的设计更清晰更易维护更易单元测试。sql和代码的分离提高了可维护性。4、提供映射标签支持对象与数据库的orm字段关系映射 5、提供对象关系映射标签支持对象关系组建维护 6、提供xml标签支持编写动态sql主要优势之一。 回顾MyBatis在之前SSM框架中集成的方式 pom.xml: !-- mybatis --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion${mybatis.version}/version/dependency!-- mybatis-spring --dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.0/version/dependency applicationContext.xml: !-- 配置SessionFactory --bean idsessionFactoryclassorg.mybatis.spring.SqlSessionFactoryBean!-- 1:连接池 --property namedataSource refdataSource/!-- 2:读取MyBatis总配置文件 --property nameconfigLocation valueclasspath:mybatis.xml/!-- 3:配置别名扫描 --property nametypeAliasesPackage valuecn.wolfcode.crm.domain/!-- 4:加载mapper文件 --property namemapperLocations valueclasspath:cn/wolfcode/crm/mapper/*Mapper.xml/!--集成pagehelper--property namepluginsarraybean classcom.github.pagehelper.PageInterceptor!-- 这里的几个配置主要演示如何使用如果不理解一定要去掉下面的配置 --property namepropertiesvaluehelperDialectmysqlreasonabletruepageSizeZerotrue/value/property/bean/array/property/bean!--Mapper接口代理扫描器--bean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuecn.wolfcode.crm.mapper//bean mybatisCfg.xml: ?xml version1.0 encodingUTF-8? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfigurationsettings!--配置允许懒加载--setting namelazyLoadingEnabled valuetrue/!--取消关联查询积极性--setting nameaggressiveLazyLoading valuefalse/!--哪些方法触发关系查询--setting namelazyLoadTriggerMethods valueclone//settings /configuration 如何集成MyBatis pom.xml: !--整合mybatis--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion1.3.0/version/dependencymybatis-config.xml: ?xml version1.0 encodingUTF-8? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfigurationsettings!--配置允许懒加载--setting namelazyLoadingEnabled valuetrue/!--取消关联查询积极性--setting nameaggressiveLazyLoading valuefalse/!--哪些方法触发关系查询--setting namelazyLoadTriggerMethods valueclone//settings /configuration application.properties: #mybatis #给包起别名因为使用MBG生成的mapper #sql里面默认是使用的类的全限定名因此我们可以不配别名都使用全名 #mybatis.type-aliases-packagecn.wolfcode.springboot.integrase._5_mybatis.domain #加载mybatis的主配置文件 mybatis.config-locationclasspath:mybatis-config.xml我们也可以去掉MyBatis的主配置文件把懒加载的配置配置到SpringBoot的配置文件中如mybatis.configuration.lazy-load-trigger-methodsclone mybatis.configuration.aggressive-lazy-loadingfalse mybatis.configuration.lazy-loading-enabledtrue domain Setter Getter ToString public class Department {private Long id;private String name;private String sn;}mapper public interface DepartmentMapper {ListDepartment selectAll();}mapper.xml: ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecn.wolfcode.springboot._06_mybatis.mapper.DepartmentMapperselect idselectAllresultTypecn.wolfcode.springboot._06_mybatis.domain.Departmentselect id,name,sn from department/select /mapper 主配置类 注意通过MapperScan扫描器来扫描mapper的接口 SpringBootApplication MapperScan(cn.wolfcode.springboot._06_mybatis.mapper) public class MyBatisConfig {}App测试类 RunWith(SpringRunner.class) SpringBootTest(classes MyBatisConfig.class) public class App {Autowiredprivate DepartmentMapper departmentMapper;Testpublic void test(){ListDepartment list departmentMapper.selectAll();list.forEach(System.out::println);} } 常见属性 #懒加载 mybatis.configuration.lazy-loading-enabledtrue mybatis.configuration.lazy-load-trigger-methodsclone mybatis.mapper-locationsclasspath:cn/wolfcode/xxx/mapper/*Mapper.xml mybatis.type-aliases-packagecn.wolfcode.xxx.domain #连接池对象不用配置,会自动注入 集成PageHelper 回顾PageHelper在之前SSM框架中集成的方式 pom.xml: dependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper/artifactIdversion5.1.6/version/dependency 配置文件中配置pageHelper 方式一分页插件配置在mybatis的主配置文件中 ?xml version1.0 encodingUTF-8? !DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfigurationsettings!--配置允许懒加载--setting namelazyLoadingEnabled valuetrue/!--取消关联查询积极性--setting nameaggressiveLazyLoading valuefalse/!--哪些方法触发关系查询--setting namelazyLoadTriggerMethods valueclone//settings!--配置在Spring中--pluginsplugin interceptorcom.github.pagehelper.PageInterceptorproperty namereasonable valuetrue/property namehelperDialect valuemysql/property namepageSizeZero valuetrue//plugin/plugins/configuration 方式二分页插件配置在spring的配置文件中 !-- 配置SessionFactory --bean idsessionFactoryclassorg.mybatis.spring.SqlSessionFactoryBean!-- 1:连接池 --property namedataSource refdataSource/!-- 2:读取MyBatis总配置文件 --property nameconfigLocation valueclasspath:mybatis.xml/!-- 3:配置别名扫描 --property nametypeAliasesPackage valuecn.wolfcode.crm.domain/!-- 4:加载mapper文件 --property namemapperLocations valueclasspath:cn/wolfcode/crm/mapper/*Mapper.xml/!--集成pagehelper--property namepluginsarraybean classcom.github.pagehelper.PageInterceptor!-- 这里的几个配置主要演示如何使用如果不理解一定要去掉下面的配置 --property namepropertiesvaluehelperDialectmysqlreasonabletruepageSizeZerotrue/value/property/bean/array/property/bean 如何集成PageHelper pom.xml: dependencygroupIdcom.github.pagehelper/groupIdartifactIdpagehelper-spring-boot-starter/artifactIdversion1.2.10/version /dependency application.properties: #pageHelper pagehelper.helper-dialectmysql pagehelper.reasonabletrue pagehelper.page-size-zerotrue 集成事务管理 回顾事务管理在之前SSM框架中的使用 方式一在spring的xml配置文件中 !-- 配置事务 --bean idtxManagerclassorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource//beantx:advice idtxAdvice transaction-managertxManagertx:attributestx:method nameget* read-onlytrue/tx:method namelist* read-onlytrue/tx:method namequery* read-onlytrue/tx:method name* propagationREQUIRED//tx:attributes/tx:adviceaop:configaop:pointcut expressionexecution(* cn.wolfcode.crm.service.*Service.*(..)) idtxPoint/aop:advisor advice-reftxAdvice pointcut-reftxPoint//aop:config 方式二使用注解的方式 !-- 配置事务管理器 --bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!-- 启用事务注解 --tx:annotation-driven transaction-managertransactionManager/ Spring中注解的方式Transactional标注事务方法。为了将方法定义为支持事务处理可以在方法上添加Transactional注解。根据Spring AOP基于代理机制只能标注公有方法。如果在类上标注Transactional注解那么这个类中所有公有方法都会被定义为支持事务。 代码如下 //添加事务注解//1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时//如何使用事务, 默认取值为 REQUIRED, 即使用调用方法的事务//REQUIRES_NEW: 事务自己的事务, 调用的事务方法的事务被挂起. //2.使用 isolation 指定事务的隔离级别, 最常用的取值为 READ_COMMITTED//3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚. 也可以通过对应的//属性进行设置. 通常情况下去默认值即可. //4.使用 readOnly 指定事务是否为只读. 表示这个事务只读取数据但不更新数据, //这样可以帮助数据库引擎优化事务. 若真的事一个只读取数据库值的方法, 应设置 readOnlytrue//5.使用 timeout 指定强制回滚之前事务可以占用的时间.Transactional(propagationPropagation.REQUIRES_NEW,isolationIsolation.READ_COMMITTED,noRollbackFor{UserAccountException.class},rollbackFor IOException.class,readOnlyfalse,timeout3)Overridepublic void purchase(String username, String isbn) {} 注意有一种情况事务会失效 TransactionalOverridepublic void purchase(String username, String isbn) {this.update(username, isbn);}Transactionalpublic void update(String username, String isbn) {// TO DO} 失效的原因是 因为spring事务是基于aop的代理机制当方法中调用this本身的方法时候即使在this的方法标明事务注解但是事务注解会失效。 解决办法 在配置中添加如下内容 !--开启aspectj代理并暴露aop代理到ThreadLocal-- aop:aspectj-autoproxy expose-proxytrue/ 将上述调用的地方改成如下: Transactional Override public void purchase(String username, String isbn) {((BookShopServiceImpl)AopContext.currentProxy()).update(username, isbn); } 如何集成事务管理 方式一 使用注解的方式 在Service的实现类上面添加Transactional注解即可。 如果是使用的springboot的较低版本需要在配置类上面使用EnableTransactionManagement开启注解可以理解为相当于 tx:annotation-driven transaction-managertransactionManager/方式二使用xml文件的方式 提供一个配置事务的xml文件。 !-- 3:配置事务管理 --!-- 3w: what where when --!-- 3.1:what 做什么增强 --bean idtxManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource//bean!-- 3.2:where: 在哪个包哪个类哪个方法下做增强 --aop:config aop:pointcut expressionexecution( * cn.wolfcode.crm.service.*Service.*(..)) idpc/aop:advisor advice-reftxAdvice pointcut-refpc//aop:config!-- 3.3:when 在什么时候做增强 --tx:advice idtxAdvice transaction-managertxManagertx:attributestx:method nameget* read-onlytrue/tx:method namelist* read-onlytrue/tx:method nameselect* read-onlytrue/tx:method namequery* read-onlytrue/tx:method namecheck* read-onlytrue/tx:method name* propagationREQUIRED//tx:attributes/tx:advice 2.在主配置文件中通过ImportResources ImportResource(classpath:tx.xml)集成FastJSON 为何要集成FastJSON fastjson可以只依赖于jdk环境其他的条件可以不用依赖 fastjson可以进行序列化和反序列换所谓的序列化就是将对象转换成对应的json字符串反序列化就是将json字符串进行转换成对应的对象 fastjson进行json转换的的速度远远大于jackjson 回顾FastJSON在之前SSM框架中的使用 pom.xml: !--fastJson解析json --dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version1.2.29/version /dependency mvc.xml mvc:annotation-driven mvc:message-converters register-defaultstrue!-- 配置Fastjson支持 --bean classcom.alibaba.fastjson.support.spring.FastJsonHttpMessageConverterproperty namesupportedMediaTypeslistvaluetext/html;charsetUTF-8/valuevalueapplication/json/valuevalueapplication/xml;charsetUTF-8/value /list/propertyproperty namefeatureslist!--配置返回json字符串是返回null值 --valueWriteMapNullValue/valuevalueQuoteFieldNames/value!-- 配置日期格式化 --valueWriteDateUseDateFormat/value/list/property/bean/mvc:message-converters /mvc:annotation-driven jsonFiled(formatyyyy-MM-dd HH:mm:ss) private Date creadate; 如何集成FastJSON pom.xml: dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version1.2.29/version /dependency 方式一 在一个配置类中定义一个bean Bean public HttpMessageConverters fastjsonHttpMessageConverters(){ //定义一个convert转换消息的对象 FastJsonHttpMessageConverter converternew FastJsonHttpMessageConverter();//添加fastjson的配置信息比如是否要格式化返回的json信息 FastJsonConfig fastJsonConfignew FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); //解决fastjson 中文乱码 ListMediaType fastMediaTypes new ArrayListMediaType();fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);//将配置信息添加到convert中 converter.setFastJsonConfig(fastJsonConfig); //将编码配置加入convert中 converter.setSupportedMediaTypes(fastMediaTypes); HttpMessageConverter? httpMessageConverterconverter; return new HttpMessageConverters(converter); } 方式二 让配置类实现 接口 WebMvcConfigurer 然后覆盖一个方法configureMessageConverters 如 Overridepublic void configureMessageConverters(ListHttpMessageConverter? converters) {// 1、需要先定义一个 convert 转换消息的对象;FastJsonHttpMessageConverter fastConverter new FastJsonHttpMessageConverter();//2、添加fastJson 的配置信息比如是否要格式化返回的json数据;FastJsonConfig fastJsonConfig new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);//3、在convert中添加配置信息.fastConverter.setFastJsonConfig(fastJsonConfig);//4、将convert添加到converters当中.converters.add(fastConverter);} 注解 // 输出到页面格式化日期格式 JSONField(format yyyy-MM-dd) // serialize:是否需要序列化属性.如果设置成false页面上就不会出现JSONField(serialize false) 集成Jackson SPringBoot已经集成了Jackson所以我们不需要导入依赖。可直接使用。 private Long id;private String name;// 输出日期到表单进行格式化 。注意必须要带上时区不然时间会减少一天JsonFormat(pattern yyyy-MM-dd,timezone GMT8)// 接收表单传来到日期进行格式化。DateTimeFormat(pattern yyyy-MM-dd)private Date hiredate;JsonIgnore // 忽略该属性在浏览器中进行显示数据private String password;集成SpringData JPA JPA是什么 SpringData其实SpringData就是Spring提供了一个操作数据的框架。而SpringData JPA只是SpringData框架下的一个基于JPA标准操作数据的模块。 SpringData JPA基于JPA的标准数据进行操作。简化操作持久层的代码。只需要编写接口就可以。 如何集成JPA 导入依赖 !--jpa--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-jpa/artifactId/dependency application.properties文件中添加配置 #jpa spring.jpa.hibernate.ddl-autoupdate spring.jpa.show-sqltrue 实体类 Entity Table(namerole) public class Role {Id //主键idGeneratedValue(strategy GenerationType.IDENTITY)//主键生成策略Column(name id)//数据库字段名private Long id;Column(name name)private String name;Column(name sn)private String sn;Overridepublic String toString() {return Role{ id id , name name \ , sn sn \ };} } 编写Dao接口 Repository public interface RoleRepository extends JpaRepositoryRole,Long {Role findRoleById(Long id);Role findRoleByName(String name);}测试 RunWith(SpringRunner.class) SpringBootTest(classes Application.class) public class JPATest {Autowiredprivate RoleRepository roleRepository;Testpublic void testFindById(){Role role roleRepository.findRoleById(2L);System.out.println(role);}Testpublic void testFindByName(){Role role roleRepository.findRoleByName(人事管理);System.out.println(role);} }SpringBoot统一异常处理 SpringBoot为何需要统一异常处理 在 Java EE 项目的开发中不管是对底层的数据库操作过程还是业务层的处理过程还是控制层的处理过 程都不可避免会遇到各种可预知的、不可预知的异常需要处理。 每个过程都单独处理异常系统的代码耦合度高工作量大且不好统一维护的工作量也很大。 那么将所有类型的异常处理从各处理过程解耦出来这样既保证了相关处理过程的功能较单一 也实现了异常信息的统一处理和维护 统一异常处理在之前SSM框架中的处理方式回顾 Spring MVC 处理异常有 3 种方式: (1)使用 Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver; (2)实现 Spring 的异常处理接口 HandlerExceptionResolver 自定义自己的异常处理器; (3)使用ExceptionHandler 注解实现异常处理;回顾方式一 SecurityException自定义异常类: public class SecurityException extends Exception {public SecurityException() { super(); } public SecurityException(String message){super(message);}} springmvc.xml中的配置全局异常处理器: bean classorg.springframework.web.servlet.handler.SimpleMappingExceptionResolver !-- 定义默认的异常处理页面当该异常类型的注册时使用 -- property namedefaultErrorView valuecommons/error / !-- 定义异常处理页面用来获取异常信息的变量名默认名为 exception -- property nameexceptionAttribute valueex / !-- 定义需要特殊处理的异常用类名或完全路径名作为 key异常也页名作为值 -- property nameexceptionMappingsvalue cn.wolfcode.web.exception.SecurityExceptioncommons/nopermission !-- 这里还可以继续扩展不同异常类型的异常处理 --/value/property /bean 回顾方式二 CustomException自定义异常类 /**** 系统自定义异常类*/ public class CustomException extends Exception {//异常信息public String message;public CustomException(String message){super(message);this.message message;}Overridepublic String getMessage() {return message;}public void setMessage(String message) {this.message message;} } 全局异常处理器 /*** * 全局异常处理器*/ public class CustomExceptionResolver implements HandlerExceptionResolver{/*** 系统抛出的异常* param httpServletRequest* param httpServletResponse* param o* param e 系统抛出的异常* return*/Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {// 解析出异常类型CustomException customException null;// 若该异常类型是系统自定义的异常直接取出异常信息在错误页面展示即可。if(e instanceof CustomException){customException (CustomException)e;}else{// 如果不是系统自定义异常构造一个系统自定义的异常类型信息为“未知错误”customException new CustomException(未知错误);}//错误信息String message customException.getMessage();ModelAndView modelAndView new ModelAndView();//将错误信息传到页面modelAndView.addObject(message,message);//指向错误页面modelAndView.setViewName(error);return modelAndView;} }错误页面 % page contentTypetext/html;charsetUTF-8 languagejava % html headtitle失败/title /head body ${message} /body /html springmvc.xml中的配置全局异常处理器: !--全局异常处理器只要类实现了HandlerExceptionResolver接口就是一个全局异常处理器哦--bean classcom.alex.ssm.exception.CustomExceptionResolver/回顾方式三 ControllerAdvice 通过使用ControllerAdvice定义统一的异常处理类而不是在每个Controller中逐个定义。ExceptionHandler用来定义函数针对的异常类型。 ErrorControllerAdvice: ControllerAdvice public class ErrorControllerAdvice {ExceptionHandler(Exception.class)public String error(Model model, Exception e){model.addAttribute(error,e.getMessage());return error;} }error.ftl: !DOCTYPE html html langen headmeta charsetUTF-8titleTitle/title /head body${error} /body /html在SpringBoot中如何统一异常处理 方式一 通过使用ControllerAdvice定义统一的异常处理类而不是在每个Controller中逐个定义。ExceptionHandler用来定义函数针对的异常类型。 ErrControllerAdvice: ControllerAdvice public class ErrControllerAdvice {ExceptionHandlerpublic String error(Exception e , Model model){model.addAttribute(error,e.getMessage());return error;} }注意如果项目中报错会被上述异常进行拦截。上述方法它会拦截到异常并把异常信息存入model中然后跳转error的页面这个页面需要自己编写在templates模版文件夹中。 error.ftl: !DOCTYPE html html langen headmeta charsetUTF-8title/title /head body我是通过注解ControllerAdvice进来的错误页面error : ${error} /body /html 利用统一异常的处理类我们可以自定义自己的异常比如自定义异常返回json格式的数据。 第一步自定义异常类 public class MyCustomException extends RuntimeException {public MyCustomException(String message) {super(message);}public MyCustomException(Throwable cause) {super(cause);} }第二步在异常的处理类中添加自定义异常的拦截方法 ExceptionHandlerResponseBodypublic JSONResult customException(MyCustomException e) {JSONResult jsonResult new JSONResult();jsonResult.setMark(e.getMessage());return jsonResult;} 第三步在service层添加异常的处理try...catch(自定义异常)) Service public class ExceptionServiceImpl {public void exception() {try {int i 1 / 0;}catch (Exception e){throw new MyCustomException(e.getMessage());}} }第四步 编写对应的controller在方法中调用service中的方法。 RequestMapping(/ex)ResponseBodypublic JSONResult list2(){ExceptionServiceImpl service new ExceptionServiceImpl();service.exception();return new JSONResult();}方式二 1,SpringBoot默认情况下把所有错误都重新定位到/error这个处理路径上由BasicErrorController类完成处理 2SpringBoot提供了默认的替换错误页面的路径 1静态错误页面默认结构 src/resources/public/error/404.html401.html5xx.html 2也可以使用模板页面 src/resources/templates/error/5xx.ftl该路径方式是通过ErrorMvcAutoConfiguration中的DefaultErrorViewResolver完成的 最后编辑于2024-11-17 10:24:55 © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点赞、收藏、关注哦
http://www.hkea.cn/news/14266194/

相关文章:

  • 网站做三方登陆需要注册公司不长春哪家网站做的好
  • 哪个公司做网站好苏州杭州专业seo服务公司
  • 人社局网站建设方案广州 天河网站设计
  • 富阳区住房与建设局网站网站开发工程师 英文
  • 网站搜索防止攻击南宁seo网站建设费用
  • 肇庆网站建设咨询高端网站建设机构
  • 做房产经纪人要自己花钱开网站吗南京谷歌优化
  • 微网站建设高端网站定制网站宣传平台
  • 企业网站文案外包微信公众号直接同步到wordpress
  • 怎么网站是什么语言做的买手机的网站
  • 我想给图书网站做代理网站建设能
  • 影视公司宣传片wordpress后台优化
  • 电子毕业设计网站建设做网站学不需要做后台管理系统
  • 网站内容如何建设国外做电商平台的网站有什么
  • 简约中文网站设计欣赏百度竞价被换着ip点击
  • 做蔬菜的网站有哪些wordpress 博客不显示
  • 南阳建设网站制作免费策划方案平台
  • 通过apache建设网站crm软件定制
  • 西宁市建设网站价格低网店美工的意义与发展
  • 网站推广的主要方式wordpress云主机模板
  • 建设项目招标网站网站设计与开发专业
  • 网站建设实训心得体会2000字网站建立需要多久
  • 茂名模板建站定制知名的网页设计师
  • mvc5 网站开发美学 pdfwordpress 数据
  • php建设网站灰色seo推广
  • 广州网站建设很棒 乐云践新ppt模板免费下载软件
  • 厦门网站建设培训费用无锡网站建设课程
  • 漯河企业网站建设江苏省建设厅网站证件查询
  • 免费素材网站素材库网站开发游戏程序开发
  • 找图纸的网站安卓应用市场免费下载安装