YAML (YAML Ain't a Markup Language)YAML不是一种标记语言,一般以.yml为后缀的文件,是一种直观的可以被电脑识别的数据序列化格式,而且容易被人类阅读,容易和脚本语言交互的,能够被支持YAML库的不一样的编程语言程序导入,一种专门用来写配置文件的语言。html
YML是代替XML的最优解决方案,语法简洁,清晰易读,跨平台性和扩展性良好好,能够表达复杂的数据结构;java
基本语法:node
1.数据以key: value
键值对的形式存储web
须要强调的是冒号后面必须有一个空格redis
name: jerry
2.不区分数据类型spring
name: jerry age: 18
3.使用缩进来表示做用域,相同缩进的键值对处于同一个级别shell
student: name: jerry age: 18
4.[]表示数组或集合数据库
numbser: [1,2,3,4]
5.{}能够在同一行书写map/对象apache
maps: {key1: value1,key2: value2}
6.数组和字典中的元素也可使用 -
来分隔到多行编程
#字符数组/list: hobby: - game - music #存储map/对象的 数组/list: dogs: - name: 阿花 age: 1 - name: 啊丑 age: 2 - {name: 啊啊,age: 3}
7.日期
birthday: 2020/12/12 10:10:10
8.文档块,可在同一个文件中编写两份不一样的配置
server: port: 8081 spring: profiles: active: prod #激活对应的文档块 --- server: port: 8083 spring: profiles: dev #指定属于哪一个环境 --- server: port: 8084 spring: profiles: prod #指定属于哪一个环境
java类:
public class Person { private String name; private int age; private String[] hobby; private HashSet<String> gfs; private Map<String,String> maps; private Dog dog; private List<Dog> dogs; private Date birth; public Date getBirth() { return birth; } } class Dog { private String name; }
yml:
person: name: jerry age: 18 hobby: #[game,music] - game - music gfs: [a,b,c] maps: {key1: value1,key2: value2} #maps: # key1: value1 #key2: value2 dog: name: 大黄 dogs: - name: 阿花 age: 18 - name: 啊丑 age: 20 birth: 2020/12/12 23:56:10
1.当容器中的bean须要使用配置文件中的内容时,可使用@Value注解:固然要保证该类的Bean以及加入容器
@Value("${myname}") private String myname;
2.当有不少属性都要注入到Bean中时能够采用@ConfigurationProperties
注解,SpringBoot会按照属性名称进行注入,注意:必须提供set方法
@Component //perfix指定要映射的key名称 与配置文件中对应 @ConfigurationProperties(prefix = "person") public class Person { private String name; private int age; public String getName() {return name;} public void setName(String name) {this.name = name;} public int getAge() {return age;} public void setAge(int age) {this.age = age;} }
在项目开发过程当中咱们为了避免影响线上数据,一般会使用一套专门用于开发阶段的配置,在编写完成后再切换到线上配置好比redis,zookeeper,数据库等等,SpringBoot能够帮助咱们轻松实现配置文件的切换;
根据不一样使用场景,建立格式为application-环境标识.yml(/properties)
的配置文件,例如:
application-dev.yml
application-prod.yml
方式一:
建立名为application-dev.yml的配置文件,SpringBoot默认会读取该文件,在文件中指定要使用的配置文件信息:
spring: profiles: active: dev #dev即为环境标识
方式二
不须要建立默认的application.yml,而是在运行程序时经过参数来指定要使用的配置文件
java -jar -Dspring.profiles.active=prod /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar
java -jar /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar --spring.profiles.active=prod
注意:使用该方式则必须在引导类中将获取的命令行参数传递给SpringBoot
@SpringBootApplication public class Application { public static void main(String[] args) { //args 即为命令行参数 SpringApplication.run(Application.class,args); } }
# ---------------------------------------- # WEB PROPERTIES # ---------------------------------------- # EMBEDDED SERVER CONFIGURATION (ServerProperties) server.port=8080 # Server HTTP port. server.servlet.context-path= # Context path of the application. server.servlet.path=/ # Path of the main dispatcher servlet. # HTTP encoding (HttpEncodingProperties) spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly. # JACKSON (JacksonProperties) spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance, `yyyy-MM-dd HH:mm:ss`. # SPRING MVC (WebMvcProperties) spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the dispatcher servlet. spring.mvc.static-path-pattern=/** # Path pattern used for static resources. spring.mvc.view.prefix= # Spring MVC view prefix. spring.mvc.view.suffix= # Spring MVC view suffix. # DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties) spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. spring.datasource.password= # Login password of the database. spring.datasource.url= # JDBC URL of the database. spring.datasource.username= # Login username of the database. # JEST (Elasticsearch HTTP client) (JestProperties) spring.elasticsearch.jest.password= # Login password. spring.elasticsearch.jest.proxy.host= # Proxy host the HTTP client should use. spring.elasticsearch.jest.proxy.port= # Proxy port the HTTP client should use. spring.elasticsearch.jest.read-timeout=3s # Read timeout. spring.elasticsearch.jest.username= # Login username.
参考官网:去看看
<!-- 配置使用redis启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
单机
spring: redis: host: 10.211.55.6 port: 6379 #Sprin boot 默认使用的是lettuce做为redis客户端,使用异步IO,且线程安全 lettuce: pool: max-active: 10 max-idle: 5 #链接池不是必须的配置项,基础配置只须要host和port便可
集群
spring: redis: cluster: nodes: 10.211.55.6:6379,10.211.55.6:6380,10.211.55.6:6381,10.211.55.6:6382,10.211.55.6:6383,10.211.55.6:6384 #节点之间使用逗号隔开
@Service public class UserServiceImpl implements UserService { @Autowired StringRedisTemplate redisTemplate; @Autowired UserMapper mapper; @Autowired ObjectMapper objectMapper;//用于json序列化 @Override public List<User> getAll() { try { //从redis获取数据 String users_json = redisTemplate.opsForValue().get("users"); //若是存在则直接返回 if (users_json != null && users_json.length() > 0){ System.out.println("缓存数据......."); return objectMapper.readValue(users_json,List.class); }else{ //不存在则查询数据库 List<User> users = mapper.selectUserList(); //并放入redis redisTemplate.opsForValue().set("users",objectMapper.writeValueAsString(users)); //返回 return users; } } catch (JsonProcessingException e) { e.printStackTrace(); } return mapper.selectUserList(); } }
请求测试:http://localhost:8080/user/list,能够看到输出缓存数据
表示redis已正常工做
涉及数据库的操做就免不了事务,在ssm项目中咱们须要配置事务管理器等相关信息,这写配置但多数状况下也都是差很少的,因此在SpringBoot中,咱们不须要编写任何的配置信息,只要在须要进行事务管理的方法上添加事务注解便可
事务测试案例:
@Service public class UserServiceImpl implements UserService { @Override @Transactional(propagation = Propagation.REQUIRED) public void updateUser(){ User user = mapper.selectUserById(1); user.setUsername("JERRY1"); mapper.updateByPrimaryKey(user); int i = 1/0; } }
若不生效可在引导类上添加@EnableTransactionManagement
注解
@EnableTransactionManagement public class Application { public static void main(String[] args) { //启动Spring boot 须要指定引导类 SpringApplication.run(Application.class,args); } }
当咱们加入了web的起步依赖后,SpringBoot就已经自动的配置了日志了,其默认使用的是slf4j+logback,并将日志直接输出到控制台,一些状况下咱们须要本身来修改日志的一些参数,如级别,输出位置等;
日志的起步依赖:固然这不须要咱们本身添加,SpringBoot已经有了
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency>
@Controller public class UserController { //获取一个logger private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired UserService service; @RequestMapping("/show") public String showList(Model model){ logger.info("request path:/show"); logger.info("request path:/show"); logger.debug("request path:/show"); logger.warn("request path:/show"); List<User> all = service.getAll(); model.addAttribute("userList",all); return "userlist"; } }
logging: level: root: info # rootLogger的级别 com.kkb.controller: debug #某个包的日志级别 file: path: ./logs/ #日志输出目录 max-size: 1GB #文件大小 max-history: 5 #文件个数 pattern: console: "%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger-%msg哈哈哈哈%n"
logback的配置文件基本上和log4j差很少,但仍然有一些差异,当咱们须要对日志进行详细的定制时无疑会增长咱们的学习成本,推荐直接使用log4j,单从对比数据上来看log4j更有优点;
使用前须要先将本来的logback依赖排除掉,而后添加log4f的依赖
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!--找到spring-web的起步依赖 排除logback--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
在resources下提供log4j2.xml
日志配置:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <!--自定义属性信息--> <properties> <property name="LOG_HOME">logs</property> <property name="FILE_NAME">applog</property> </properties> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <!--滚动日志配置 filePattern用于设置滚动文件的命名规则 若以.zip为结尾则会自动归档日志文件 也支持其余的格式.gz, .zip, .bz2, 等--> <RollingRandomAccessFile name="RollingAppender" fileName="${LOG_HOME}/${FILE_NAME}.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i.log"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> <Policies> <!--滚动时间间隔 该参数需结合filePattern中的时间格式 此时表示为1分钟更换一个新文件 若时间格式为%d{yyyy-MM-dd HH}则表示每小时更换一个新文件--> <TimeBasedTriggeringPolicy interval="1"/> <!--单个日志文件最大容量 --> <SizeBasedTriggeringPolicy size="1 MB"/> </Policies> <!--最大保留的日志文件个数 默认为7个 --> <DefaultRolloverStrategy max="20"/> </RollingRandomAccessFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> <Logger name="com.kkb.controller" level="debug"> <AppenderRef ref="RollingAppender"/> <AppenderRef ref="Console"/> </Logger> </Loggers> </Configuration>
若名称不是默认的log42.xml
则能够在springboot中添加配置来指定:
logging: config: classpath:log4j3.xml
还记得拦截器是用来干什么的吗,它在何时执行?
在web-mvc中咱们已经认识了拦截器,它能够在一个请求到达Handler处理以前对请求进行拦截,从而能够轻松的实现权限控制,登陆认证等功能;
public class LogginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器执行.................."); if (request.getRequestURI().contains("login")){ return true; } if (request.getSession().getAttribute("user") == null){ response.sendRedirect("/login.html"); return false; } return true; } }
@RequestMapping("/login") public String userLogin(User user, HttpSession session){ User u = service.userLogin(user); if (user.getUsername().equals("jerry") && user.getPassword().equals("123")){ session.setAttribute("user",user); return "redirect:/show"; } return "redirect:/login.html"; } @RequestMapping("/login.html") public String getage(){ return "login"; }
@Configuration public class MyConfigruation implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogginInterceptor()).addPathPatterns("/**"); } }
webmvc中异常处理采用的是AOP,我开门只须要提供用于处理异常的通知便可
@ControllerAdvice //异常处理使用的是AOP 因此处理逻辑 将作为通知被织入 public class GlobalExceptionHandler { //日志记录器 private Logger logger = LoggerFactory.getLogger(getClass()); //指定该方法能够处理的异常类型 @ExceptionHandler(Exception.class) //model 用于向错误页面传递数据 public String defaultHandler(Model model,Exception e){ model.addAttribute("error",e.getMessage());//添加错误信息 logger.error(e.getMessage(),e);//输出到日志 return "error";//跳转error.html } }
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>系统错误</h1> 缘由:<span th:text="${error}" style="color:red"/> </body> </html>
在pom中添加SpringBoot的maven插件,这将使得maven打包时会将全部依赖的jar包所有打包,造成一个fat jar,这样一来只要有java环境就能运行工程了,不须要在配置相关的依赖;
添加插件:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin>
执行命令:
#cd到工程根目录下: mavem package #打包前会先执行项目中的全部单元测试,若不须要运行测试可使用如下参数跳过测试直接打包 maven -DskipTests package
运行打包好的项目:
#打包完成后会在项目根目录下生产target目录,里面就包含了打包完的jar,进入target后执行如下命令便可 java -jar ./target/SpringBootDemo-1.0-SNAPSHOT.jar
服务提供方和消费方依然是独立的项目,各自管理本身的依赖关系,而后抽取公共部分
建立工程:
| common (空的maven) | HelloService | provider (dubbo + SpringBot) | HelloServiceImpl | consumer (dubbo + SpringBot + webMVC) | HelloController
pom文件:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.11</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency>
实现类:
@Service //注意 要使用dubbo提供的Service注解 public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "hello "+name; } }
配置文件:
dubbo: application: name: my-provider qos-enable: false registry: protocol: zookeeper address: 10.211.55.5:2182 protocol: name: dubbo port: 21888
引导类:
@SpringBootApplication @EnableDubbo public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
pom文件:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.11</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> </dependencies>
控制器:
@RestController public class HeolloController { @Reference HelloService helloService; @RequestMapping("/test/{name}") public String serviceTest(@PathVariable String name){ return helloService.sayHello(name); } }
配置文件:
dubbo: application: name: my-consumer qos-enable: false registry: protocol: zookeeper address: 10.211.55.5:2182 #集群写法 address: zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181,192.168.50.134:2181
引导类:
@SpringBootApplication public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class,args); } }
访问测试:http://localhost:8080/test/jerry
页面输出名字即访问成功
Dubbo的pom文件和普通的SpringBoot略微不一样,不用指定parent