spring学习笔记
Spring实战学习笔记之SpEL表达式
Spring实战学习笔记之SpEL表达式在Spring XML配置⽂件中装配Bean的属性和构造参数都是静态的,⽽在运⾏期才知道装配的值,就可以使⽤SpEL实现SpEL表达式的⾸要⽬标是通过计算获得某个值。
在计算这个数值的过程中,会使⽤到其他的值并会对这些值进⾏操作。
SpEL特性:(1)、使⽤Bean的ID来引⽤Bean;(2)、调⽤⽅法和访问对象的属性;(3)、对值进⾏算术、关系和逻辑运算;(4)、正则表达式匹配;(5)、集合操作#{ }标记会提⽰ Spring这个标记⾥的内容是SpEL表达式。
最简单的属性注⼊:<property name="count" value="#{5}" />还可以与⾮SpEL表达式的值混⽤:<property name="message" value="The value is #{5}" />浮点数value="#{89.7}" 科学记数法value="#{1e4}"=====>10000.0String类型的字⾯值:<property name="name" value="#{'Tom'}" />或<property name="name" value='#{"Tom"}' /> 单引号和双引号相互包含的⽅式使⽤布尔类型:<property name="enable" value="#{false}" />引⽤Bean:<property name="userDao" value="#{userDao}" />等价于<property name="userDao" ref="userDao" />引⽤Bean属性:<property name="orderOwner" value="#{}" />类似代码:User user=newUser();order.setOrderOwner(user.getName());引⽤Bean的⽅法:<property name="currUser" value="#{userDao.getCurrUser()}" />(假设userDao内有公共⽅法getCurrUser())现在如果想把userDao.getCurrUser()得到的当前英⽂⽤户名转为⼤写字母:<property name="currUser" value="# {userDao.getCurrUser().toUpperCase()}" />,这时如果得到的⽤户名为空(null),则会抛NullPointerException异常,为了避免异常,可以使⽤?.代替点(.),如:<property name="currUser" value="#{userDao.getCurrUser()?.toUpperCase()}" />这样null后⾯的⽅法不再执⾏SpEL表达式中使⽤T( )运算符访问指定类的静态⽅法和常量。
SpringBootActuator学习笔记
SpringBootActuator学习笔记spring boot ActuatorActuator概述Actuator指的是负责和移动装置的组件。
通过Actuator暴露的端点我们可以获取⼀个正在运⾏中的应⽤内部的状态导⼊依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>Actuator具备⼀些开箱即⽤的端⼝Endpoints id描述HTTP⽅法是否敏感信息auditevents显⽰当前应⽤程序的审计事件信息GET Yesbeans显⽰应⽤上下⽂中创建的所有Bean GET Yescaches显⽰可⽤缓存信息GET Yesconditions显⽰⾃动装配类的状态及及应⽤信息GET Yesconfigprops显⽰所有 @ConfigurationProperties 列表GET Yesenv显⽰ ConfigurableEnvironment 中的属性GET Yesflyway显⽰ Flyway 数据库迁移信息GET Yeshealth显⽰应⽤的健康信息(未认证只显⽰status,认证显⽰全部信息详情)GET Noinfo显⽰任意的应⽤信息(在资源⽂件写info.xxx即可)GET Noliquibase展⽰Liquibase 数据库迁移GET Yesmetrics提供应⽤运⾏状态的完整度量指标报告GET Yesmappings显⽰所有 @RequestMapping 路径集列表GET Yes scheduledtasks显⽰应⽤程序中的计划任务GET Yessessions允许从Spring会话⽀持的会话存储中检索和删除⽤户会话。
spring知识点总结
spring知识点总结Spring是一个开发应用程序的Java企业应用程序框架,它以依赖注入(DI)和面向切面(AOP)为基础,可以帮助开发者开发出模块化、可重用、可扩展、可测试的应用程序。
Spring可以用来构建Web应用程序、基于REST的服务、批处理应用程序以及各种不同类型的企业级应用程序。
下面是关于Spring的一些重要知识点总结:1. 控制反转(Inversion of Control,简称IoC):Spring的核心特性之一,通过IoC容器将对象的创建和依赖注入交给框架来管理,减少了代码的耦合度和管理对象的复杂性。
2. 依赖注入(Dependency Injection,简称DI):是IoC的一种实现方式,通过注解或配置文件将对象的依赖关系注入到对象中,使得对象在创建时不需要自己构造依赖的对象。
3. AOP(Aspect-Oriented Programming):面向切面编程,通过将横切关注点(如日志记录、安全性检查等)模块化,便于代码的维护和管理。
4. Spring MVC:用于构建Web应用程序的模块,提供了一种基于注解的方式来处理用户请求和生成响应,支持RESTful风格的开发。
5. 事务管理:Spring提供了对事务的支持,可以通过注解或配置文件的方式管理数据库事务,保证数据一致性和完整性。
6. 数据访问支持:Spring可以与各种数据访问技术(如JDBC、Hibernate、MyBatis等)无缝集成,简化了数据库操作的开发过程。
7. Spring Boot:Spring框架的一个子项目,用于简化Spring应用程序的配置和部署,提供了自动配置、嵌入式服务器等特性,使得开发者可以快速搭建一个可运行的Spring应用程序。
8. Spring Security:用于开发安全性强的应用程序,提供用户认证、授权、身份验证等功能。
9. Spring Cloud:基于Spring Boot开发的微服务框架,提供了服务发现、负载均衡、熔断器、配置管理等功能,帮助开发者构建分布式系统。
SpringBoot学习笔记
10分钟创建一个SB应用:1.创建项目2将springboot的版本改为1.5.6(不修改后面操作数据库会报类找不到)<version>1.5.6.RELEASE</version>3.pom.xml中配置3个数据库相关的内容4.在入口文件增加注解(不注解会导致mapper识别不到):@MapperScan("com.example.demo.mapper")5.创建generator/generatorConfig.xml文件,并修改数据库账号密码、包名、表名6.修改application.yml,增加数据源相关的配置7.创建一个maven的Run配置,设置mybatis-generator:generate -e8.编写Service接口和Service实现类9.编写Controller和方法10.启动应用创建项目https:///lom9357bye/article/details/69677120通过tomcat部署项目https:///PJH-Forever/p/8026330.htmlspring boot configuration annotation proessor not found in classpath引入如下依赖:<dependency><groupId> org.springframework.boot </groupId><artifactId> spring-boot-configuration-processor </artifactId><optional> true </optional></dependency>pom.xml中的parent只有parent设置了,后面的才不用写version;没有在parent中设置的,后面必须写version,否则只会下载一个unknown的错误包一些tips:spring boot 2.0相比1.5.x,变更比较大,一些类去除了,因此要注意不同版本的api如果在generatorConfig.xml中配置了某个表,但是没有用到,那么程序起来的时候会报错;删除即可Durid包含的主要功能:1)使用StaFilter插件进行监控数据库访问性能2)替换DBCP和C3P0,提供一个高效、可扩展的数据库连接池3)支持数据库密码的加密4)SQL执行日志5)提供了一个监控页面,可以查看sql情况控制器中通过@RequestBody获取POST参数报错:{"timestamp":1527154727083,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message": "Content type 'application/json;charset=UTF-8' not supported","path":"/recomd/add"}经过排查,发现是参数中的类Recommend里面,有2个setIndexList()方法:setIndexList(List xxx);setIndexList(ArrayList xxx);删除一个就正常了,猜测是RequestBody在组装Recommend这个参数类的时候,无法判断该用哪一个set方法,从而报错了这应该算是框架的一个bug了Field userMapper in erServiceImpl required a bean of type 'erMapper' that could not be found.原因是在入口文件XxxApplication中,少加了一个注解:@MapperScan("com.zhouchangju.mapper")将项目启动方式从XxxApplication改为Artifact后,访问页面都是4041.没有将pom.xml里面的启动方式从jar改为war2.XxxApplication类没有继承自SpringBootServletInitializer类extends SpringBootServletInitializer安全插件配置url的时候,不用加artifactid比如项目叫做daily,我设置antMatchers的时候,不用加daily这一截:/**定义安全策略*/@Overrideprotected void configure(HttpSecurity http) throws Exception {//配置安全策略http.authorizeRequests()//定义/请求不需要验证.antMatchers("/","/**/*.css","/**/*.js","/**/*.jpg","/**/*.png","/**/*.jpeg","/user/getdynamicpassword","/user/login","/login.html").permitAll().anyRequest().authenticated()//其余的所有请求都需要验证.and().logout().permitAll()//定义logout不需要验证.and().formLogin()//使用form表单登录.loginPage("/login.html").failureUrl("/login?error=true");}本地开发时,Security验证的接口,总是报403需要在SecurityConfig中关闭csrf:.csrf().disable()Edit Configration时,没有Tomcat Serversettings->Build,Execution,Deploment->右侧ApplicationServer->添加本地tomcat信息误删了项目模块文件xxx.iml怎么办?可以在Project Structure里面的module里面,重新导入模块,注意每一步都是import,不是createKafkaConsumer is not safe for multi-threaded access配置文件中的属性无法加载: require a bean of type ng.String that could not be found 是因为写了一个带有String参数的构造函数导致的,删除构造函数即可解决,详见:https:///questions/40670099/im-not-including-the-java-lang-string-bean maven编译项目,报错:cannot find symbol原因是svn上面代码不全,缺少了一些文件如何修改打包后的war文件的存放位置?由于maven遵循“约定优先于配置”的思想,所以如果不做特殊配置,它默认是把打包之后产生的文件都放在target目录下的。
【Spring-AOP-学习笔记-5】@AfterReturning增强处理简单示例
【Spring-AOP-学习笔记-5】@AfterReturning增强处理简单⽰例项⽬结构业务代码@Component("hello")public class HelloImpl implements Hello{// 定义⼀个简单⽅法,模拟应⽤中的业务逻辑⽅法public void foo(){System.out.println("执⾏Hello组件的foo()⽅法");}// 定义⼀个addUser()⽅法,模拟应⽤中的添加⽤户的⽅法public int addUser(String name , String pass){System.out.println("执⾏Hello组件的addUser添加⽤户:" + name);return 20;}}@Component("world")public class WorldImpl implements World{// 定义⼀个简单⽅法,模拟应⽤中的业务逻辑⽅法public void bar(){System.out.println("执⾏World组件的bar()⽅法");}}定义切⾯Bean@Aspectpublic class LogAspect{// 匹配org.crazyit.app.service.impl包下所有类的、// 所有⽅法的执⾏作为切⼊点@AfterReturning(returning="rvt", pointcut="execution(* org.crazyit.app.service.impl.*.*(..))")// 声明rvt时指定的类型会限制⽬标⽅法必须返回指定类型的值或没有返回值// 此处将rvt的类型声明为Object,意味着对⽬标⽅法的返回值不加限制public void log(Object rvt){System.out.println("获取⽬标⽅法返回值:" + rvt);System.out.println("模拟记录⽇志功能...");}}说明:returing属性所指定的形参名必须对应增强处理中的⼀个形参名,当⽬标⽅法执⾏返回后,返回值作为相应的参数值传⼊增强处理⽅法中。
SpringBoot踩坑笔记二:SpringBoot整合redis报Noqualifyin。。。
SpringBoot踩坑笔记⼆:SpringBoot整合redis报Noqualifyin。
今天在学习Spring Boot整合redis的过程中遇到个问题,在使⽤@Autowiredprivate RedisTemplate<String, Object> redisTemplate;注⼊时,启动项⽬会报异常org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.bh.redis.RedisTest': Unsatisfied dependency expressed through field 'redisTemplate'; nested exception is org.springframework.beans.facto at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44) ~[spring-boot-test-autoconfigure-2.0.5.RELEASE.jar:2.0. at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89) [.cp/:na]at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) [.cp/:na]at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) [.cp/:na]at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) [.cp/:na]at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) [.cp/:na]at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209) [.cp/:na]Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<ng.String, ng.Object>' available: expected at least 1 bean which qualifi at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1506) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1101) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]... 29 common frames omitted这么⼀⼤串看的是不是有点懵,其实咱们看⼀句可以了No qualifying bean of type 'org.springframework.data.redis.core.RedisTemplate<ng.String, ng.Object>' available:⼤致意思是没有与RedisTemplate<String, Object>匹配的bean解决⽅法1、不指定泛型,如@Autowiredprivate RedisTemplate redisTemplate;2、使⽤@Resource注解代替@Autowired,如@Resourceprivate RedisTemplate<String, Object> redisTemplate;。
Springcloud学习笔记09-常用注解01@PostMapping、@GetMapp。。。
Springcloud学习笔记09-常⽤注解01@PostMapping、@GetMapp。
.springframework.web.bind.annotation包下注解1.1 @PostMapping、@GetMapping、@RequestMapping、@RestController、@ResponseBody、@RequestParam、@RequestPart、@PutMapping(1)@RequestMapping@RequestMapping如果没有指定请求⽅式,将接收Get、Post、Head、Options等所有的请求⽅式.(2)@GetMapping@GetMapping是⼀个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。
该注解将HTTP Get 映射到特定的处理⽅法上。
get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段⼀⼀对应,在URL中可以看到。
get是从服务器上获取数据。
若符合下列任⼀情况,则⽤GET⽅法:* 请求是为了查找资源,HTML表单数据仅⽤来帮助搜索。
* 请求结果⽆持续性的副作⽤。
* 收集的数据及HTML表单内的输⼊字段名称的总长不超过1024个字符。
(3)@PostMapping@PostMapping是⼀个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。
get⽅式的安全性较Post⽅式要差些,包含机密信息的话,建议⽤Post数据提交⽅式;post是向服务器传送数据。
若符合下列任⼀情况,则⽤POST⽅法:* 请求的结果有持续性的副作⽤,例如,数据库内添加新的数据⾏。
* 若使⽤GET⽅法,则表单上收集的数据可能让URL过长。
* 要传送的数据不是采⽤7位的ASCII编码。
(4)@requestBody(后端⽅法接收请求体)@requestBody注解常⽤来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,⽐如说:application/json或者是application/xml等。
Spring从入门到精通(共58张PPT)
REQUIRES_NEW3,、新建写事@务,开如果头当前存注在解事务,@把R当e前s事o务u挂r起c。e注入接口
Spring与Hibernate的集成
Struts+Hibernate+Spring的集成
public void init(){System.
@After 最终通知:不论一个方法是如何结束的,最终通知都运行
势。Spring 2.5 的一大增强就是引入了很多注释类,现在我们已经可以使用注解配置完
成大部分 XML 配置的功能。
基于注解的依赖注入
spring注解的使用
<prop key=“supp1ort、”> 要使用注解来代替xml的配置,要引入如下jar包:
public interface </property>
<property name=“lists”>
<list> <value></value> <ref/>
</list> </property>
<property name=“sets”> <set> <value></value> <ref/>
</set>
</property>
<property name=“maps”> <map>
注入依赖对象
在<property>或<constructor-arg>元素中使用<ref>
在<property>或<constructor-arg>元素中加上ref属性
spring成神之路第三篇:Spring容器基本使用及原理(ApplicationCont。。。
spring成神之路第三篇:Spring容器基本使⽤及原理(ApplicationCont。
1. jdk1.82. idea3. maven-3.6.14. spring-5.2.3.RELEASEIOC容器是具有依赖注⼊功能的容器,负责对象的实例化、对象的初始化,对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作,对象的整个⽣命周期都是由容器来控制。
我们需要使⽤的对象都由ioc容器进⾏管理,不需要我们再去⼿动通过new的⽅式去创建对象,由ioc 容器直接帮我们组装好,当我们需要使⽤的时候直接从ioc容器中直接获取就可以了。
那么spring ioc容器是如何知道需要管理哪些对象呢?需要我们给ioc容器提供⼀个配置清单,这个配置⽀持xml格式和java注解的⽅式,在配置⽂件中列出需要让ioc容器管理的对象,以及可以指定让ioc容器如何构建这些对象,当spring容器启动的时候,就会去加载这个配置⽂件,然后将这些对象给组装好以供外部访问者使⽤。
这⾥所说的IOC容器也叫spring容器。
由spring容器管理的对象统称为Bean对象。
Bean就是普通的java对象,和我们⾃⼰new的对象其实是⼀样的,只是这些对象是由spring去创建和管理的,我们需要在配置⽂件中告诉spring容器需要创建哪些bean对象,所以需要先在配置⽂件中定义好需要创建的bean对象,这些配置统称为bean定义配置元数据信息,spring容器通过读取这些bean配置元数据信息来构建和组装我们需要的对象。
1. 引⼊spring相关的maven配置2. 创建bean配置⽂件,⽐如bean xml配置⽂件3. 在bean xml⽂件中定义好需要spring容器管理的bean对象4. 创建spring容器,并给容器指定需要装载的bean配置⽂件,当spring容器启动之后,会加载这些配置⽂件,然后创建好配置⽂件中定义好的bean对象,将这些对象放在容器中以供使⽤5. 通过容器提供的⽅法获取容器中的对象,然后使⽤spring内部提供了很多表⽰spring容器的接⼝和对象,我们来看看⽐较常见的⼏个容器接⼝和具体的实现类。
spring3.0学习笔记二---SpEL表达式1
spring3.0学习笔记二---SpEL表达式1相对来讲,java是一门静态语言。
而我们今天要讲的是一门动态“语言”---SpEL。
动态语言和静态语言的最显著差别在于,举个例子," 'Hello'.toUperCase()"这只是一个普通的字符串,差别在于能否把它编译和运行起来得到结果。
就是说动态语言能把一个字符串解释成程序语句。
如果还不是很明白的话没关系,看下面的SpEL例子。
(接下去的我就用例子来做介绍了)public void testSpEL1() {//ExpressionParser是Spring3里的一个包,用来动态解释一个字符串。
ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression(" 'Hello,World' ");System.out.println((String)exp.getV alue());}这里'Hello,World' 是一个字符串,解释起来还是一个字符串,所以打印结果是:Hello,World第二个例子:调用方法public void testSpEL2() {ExpressionParser parser = new SpelExpressionParser();Expression exp=parser.parseExpression(" 'Hello'.concat(' World!')"); //这里调用了字符串String的concat 方法//Expression exp=parser.parseExpression("newString('helloworld').toUpperCase()");Stringmessage=(String)exp.getV alue();}第三个例子:调用属性ExpressionParser parser= new SpelExpressionParser();Expression exp=parser.parseExpression("'HelloWorld'.bytes"); //得到字符串的byte//Expression exp=parser.parseExpression("'HelloWorld'.bytes.length"); //得到属性的属性byte [] bytes=(byte[])exp.getV alue();第四个例子:调用类中的属性(下面开始复杂起来了)@Resourcepublic User user; //注入之后,user.getName() 为xiaolingpublic void testSpEL() {//设“值域”,限定在u这个对象里EvaluationContext context = new StandardEvaluationContext(user);ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("username"); //==user.getUsername() System.out.println((String)exp.getV alue(context)); //结果:xiaoling}或者用更简洁的一个方式:System.out.println((String)exp.getV alue(user));这样就不用设值域了!呵呵!第五个例子:给对象中的属性设值StandardEvaluationContext context = new StandardEvaluationContext(user); parser.parseExpression("username").setV alue(context, "ling");第六个例子:做判断Expression exp=parser.parseExpression("name=='xiaoling' ");boolean result=exp.getV alue(context,Boolean.class); //evaluate stotrue打印出来,结果为true看到这,可能你还是一头雾水:这算什么新特性啊,哪有什么用处!用处就在于,SpEL把java变成“动”的了!(纯属我个人观点!!)接下来,我们把SpEL用到bean.xml中去先看个例子(例一)<bean id="numberGuess" class="cn.ling.spel.NumberGuess"><property name="randomNumber" value="#{T(ng.Math).random()*100.0}"/></bean>怎么样,可以在xml文件里面赋值了!呵呵!value里面都用#{}来赋值。
我的spring学习笔记14-容器扩展点之PropertyPlaceholderConfigurer
PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是BeanFactoryPostProcessor接口的一个实现。
关于BeanFactoryPostProcessor和BeanPostProcessor类似。
我会在其他地方介绍。
PropertyPlaceholderConfigurer可以将上下文(配置文件)中的属性值放在另一个单独的标准java Properties文件中去。
这样的话,我只需要对properties文件进行修改,而不用对xml配置文件进行修改。
作用是什么呢?有一些属性值不需要经常变更,但是有一些属性值可能随时改变,把经常会改动的属性值放在另一个文件中的话,程序使用起来也更方便。
下面将通过一个例子来理解PropertyPlaceholderConfigurer。
首先是配置文件,代码如下:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="xmlns:xsi="xmlns:util="xsi:schemaLocation="<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="propertyPlaceHolder.properties"/></bean><bean id ="student" class="co.jp.beanFactoryPost.Student"><property name="name"><value>${name}</value></property><property name="age"><value>${age}</value></property><property name="birth"><value>${birth}</value></property></bean></beans>在这个配置文件中最重要的就是下面这段代码,<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="propertyPlaceHolder.properties"/></bean>PropertyPlaceholderConfigurer会读取location所设定的属性文件,并将properties文件中的值,设定给${name},${age},${birth}从而完成依赖注入。
SpringMVC学习笔记
SpringMVC学习笔记作者:胡晟源。
QQ:1312837781配置spring提示:1 Spring Tool Suit (STS)2 Hibernate Tools对于JUNO版本的Eclipse 可以在help->Eclipse Marketplace 输入插件的名字在列表中选择插件安装就可以了。
SpringMvc原理图解:导入jar包一:springmvc工作流程。
①.servlet容器初始化一个request请求②.DispatcherServlet分发器负责发送请求到映射器.③.despatcherServlet把请求交给处理器映射Mapping,mapping来寻找需要执行的control④.处理器映射把请求分发给控制器Controler。
⑤.Controler执行完毕后返回ModelAndView(视图解析器)⑥.把ModelAndView返回给dispatcherServlet核心分发器⑦.由于DespatcherServlet不参与具体的处理,所以把modelAndView交给视图解析器。
⑧.视图解析器解析成一个真正的视图,再发给view然后response。
ParameterizableViewController(参数控制器)①.在springmvc-servlet.xml里面加上配置②.通过参数控制器访问页面流程解析:也可以直接在参数控制器里定义name属性,直接通过name属性地址来访问。
如下:但要注意的是:配置文件里必须有BeanNameUrlHandlerMapping情况下,默认映射将会被覆盖;以name属性;来访问将会失败。
命令控制器③.在springmvc里面有如下配置。
④.使用简单url进行访问,参数被封装进javabean。
http://localhost:8080/mysm/comm.do?id=1&userName=zhangsan&password=123&age=13 命令控制器①.首先:springMVC有三个映射器,如果不定义映射Mapping,那么就会使默认:●<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>也就是说:上面这个定义和不定义都是一样的。
Spring Security学习总结二
Spring Security学习总结二前一篇文章里介绍了Spring Security的一些基础知识,相信你对Spring Security的工作流程已经有了一定的了解,如果你同时在读源代码,那你应该可以认识的更深刻。
在这篇文章里,我们将对Spring Security进行一些自定义的扩展,比如自定义实现UserDetailsService,保护业务方法以及如何对用户权限等信息进行动态的配置管理。
一自定义UserDetailsService实现UserDetailsService接口,这个接口中只定义了唯一的UserDetails loadUserByUsername(String username)方法,它通过用户名来获取整个UserDetails对象。
前一篇文章已经介绍了系统提供的默认实现方式InMemoryDaoImpl,它从配置文件中读取用户的身份信息(用户名,密码等),如果你的客户想修改用户信息,就需要直接修改配置文件(你需要告诉用户配置文件的路径,应该在什么地方修改,如何把明文密码通过MD5加密以及如何重启服务器等)。
听起来是不是很费劲啊!在实际应用中,我们可能需要提供动态的方式来获取用户身份信息,最常用的莫过于数据库了,当然也可以是LDAP服务器等。
本文首先介绍系统提供的一个默认实现类 JdbcDaoImpl(erdetails.jdbc. JdbcDaoImpl),它通过用户名从数据库中获取用户身份信息,修改配置文件,将userDetailsService Bean的配置修改如下:1<bean id="userDetailsService"2class="erdetails.jdbc.JdbcDaoImpl"3p:dataSource-ref="dataSource"4p:usersByUsernameQuery="select userName, passWord, enabled, from users where userName=?"5p:authoritiesByUsernameQuery="selecterName,r.roleName from users u,roles7r,users_roles ur where erId=erId and8r.roleId=ur.roleId and erName=?"/>JdbcDaoImpl类继承自Spring Framework的JdbcDaoSupport类并实现了UserDetailsService接口,因为从数据库中读取信息,所以首先需要一个数据源对象,这里不在多说,这里需要重点介绍的是usersByUsernameQuery和authoritiesByUsernameQuery,属性,它们的值都是一条SQL语句,JdbcDaoImpl 类通过SQL从数据库中检索相应的信息,usersByUsernameQuery属性定义了通过用户名检索用户信息的SQL语句,包括用户名,密码以及用户是否可用,authoritiesByUsernameQuery属性定义了通过用户名检索用户权限信息的SQL 语句,这两个属性都引用一个MappingSqlQuery(请参考Spring Framework相关资料)实例,MappingSqlQuery的mapRow()方法将一个ResultSet(结果集)中的字段映射为一个领域对象,Spring Security为我们提供了默认的数据库表,如下图所示(摘自《Spring in Action》):图<!——[if supportFields]——>1<!——[if supportFields]——> JdbcDaoImp数据库表如果我们需要获取用户的其它信息就需要自己来扩展系统的默认实现,首先应该了解一下UserDetailsService实现的原理,还是要回到源代码,以下是JdbcDaoImpl类的部分代码:1private class UsersByUsernameMapping extends MappingSqlQuery {3protected UsersByUsernameMapping(DataSource ds) {5super(ds, usersByUsernameQuery);7declareParameter(new SqlParameter(Types.VARCHAR));9compile();11}13protected Object mapRow(ResultSet rs, int rownum) throws SQLException {15String username = rs.getString(1);17String password = rs.getString(2);19boolean enabled = rs.getBoolean(3);21UserDetails user = new User(username, password, enabled, true,23true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); 25return user;26}28}也许你已经看出什么来了,对了,系统返回的UserDetails对象就是从这里来的,这就是读源代码的好处,DaoAuthenticationProvider提供者通过调用自己的authenticate(Authentication authentication)方法将用户在登录页面输入的用户信息与这里从数据库获取的用户信息进行匹配,如果匹配成功则将用户的权限信息赋给 Authentication对象并将其存放在SecurityContext 中,供其它请求使用。
马士兵Spring课堂笔记(超级详细版)
课程内容---…详细包括整合struts hibernate------------------------------------1.面向接口(抽象)编程的概念与好处2.IOC/DI的概念与好处a)inversion of controlb)dependency injection3.AOP的概念与好处4.Spring简介5.Spring应用IOC/DI(重要)a)xmlb)annotation6.Spring应用AOP(重要)a)xmlb)annotation7.Struts2.1.6 + Spring2.5.6 + Hibernate3.3.2整合(重要)a)opensessionInviewfilter(记住,解决什么问题,怎么解决)8.Spring JDBC面向接口编程…(面向抽象编程)1.场景:用户添加2.Spring_0100_AbstractOrientedProgramminga)不是AOP:Aspect Oriented Programming3.好处:灵活什么是IOC(DI),,,有什么好处1.把自己new的东西改为由容器提供a)初始化具体值b)装配<?xml version="1.0"?>-<beans><bean class="erDAOImpl" id="u"/>(class 是个类。
Id就等于构造了一个对象)<bean class="erService" id="userService"><property bean="u" name="userDAO"/> </bean>(把u这个对象注入到UserService这个类的一个userDAO的一个属性里)-</beans>2.好处:灵活装配Spring简介包括整合struts hibernate------------------------------------1.项目名称:Spring_0200_IOC_Introduction2.环境搭建a)只用IOCi.spring.jar , jarkata-commons/commons-loggin.jar3.IOC容器a)实例化具体beanb)动态装配4.AOP支持a)安全检查b)管理transactionSpring IOC配置与应用1.FAQ:不给提示:a)window – preferences – myeclipse – xml – xml catalogb)User Specified Entries – addi.Location: D:\share\0900_Spring\soft\spring-framework-2.5.6\dist\resources\spring-beans-2.5.xsdii.URI:file:///D:/share/0900_Spring/soft/spring-framework-2.5.6/dist/resources/spring-beans-2.5.xsd iii.Key Type: Schema Locationiv.Key: /schema/beans/spring-beans-2.5.xsd2.注入类型a)Spring_0300_IOC_Injection_Typeb)setter(重要)c)构造方法(可以忘记)d)接口注入(可以忘记)3.id vs. Name(可以把Id换成name,没什么区别!)a)Spring_0400_IOC_Id_Nameb)name可以用特殊字符4.简单属性的注入a)Spring_0500_IOC_SimplePropertyb)<property name=… value=….>在配置文件里直接赋值!(在此简单属性为int和string,会自动转换)5.<bean 中的scope属性a)Spring_0600_IOC_Bean_Scopeb)singleton 单例(无论去多少次都是同一个bean)c)proptotype 每次创建新的对象6.集合注入a)Spring_0700_IOC_Collectionsb)很少用,不重要!参考程序7.自动装配a)Spring_0800_IOC_AutoWireb)byNamec)byTyped)如果所有的bean都用同一种,可以使用beans的属性:default-autowire-<bean class="erDAOImpl" name="userDAO"><property name="daoId" value="1"/> </bean><bean class="erDAOImpl" name="userDAO2"><property name="daoId" value="2"/> </bean><bean class="erService"autowire="byType" scope="prototype" id="userService"></bean> </beans>(这里会报错,因为有两个userDAO和UserDAO2都是int类型!)(如果说byname则会显示第一个的内容“1”!,因为UserService类里面的userDAO属性与第一个的名字一样!)8.生命周期a)Spring_0900_IOC_Life_Cycleb)lazy-init (不重要)c)init-method与destroy-methd 不要和prototype一起用(了解)<bean class="erDAOImpl" id="u"></bean><bean class="erService" id="userService" scope="prototype"destroy-method="destroy" init-method="init"></bean></beans>9.Annotation第一步:a)修改xml文件,参考文档<context:annotation-config />b)默认按类型by typec)如果想用byName,使用@Qulifierd)写在private field(第三种注入形式)(不建议,破坏封装)e)如果写在set上,@qualifier需要写在参数上f)10.@Resource(重要)a)加入:j2ee/common-annotations.jarb)默认按名称,名称找不到,按类型c)可以指定特定名称d)推荐使用e)不足:如果没有源码,就无法运用annotation,只能使用xml11.@Component@Service @Controller @Repository(四个一样的功能!!)a)初始化的名字默认为类名首字母小写b)可以指定初始化bean的名字首先先加载ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 即读beans.xml里面的内容,然后通过找从com.bjsxt开始“scan”含@component的类,找到之后就初始化对象,结果在其一个属相的set方法上找到一个源为“u”的一个bean,于是就加载那个bean!12.@Scope13.@PostConstruct = init-method;(在构造对象后执行此方法)@PreDestroy = destroy-method;(在容器销毁前执行此方法)什么是AOP1.面向切面编程Aspect-Oriented-Programminga)是对面向对象的思维方式的有力补充2.Spring_1400_AOP_Introduction3.好处:可以动态的添加和删除在切面上的逻辑而不影响原来的执行代码a)Filterb)Struts2的interceptor4.概念:a)JoinPoint 释意:切面与原方法交接点即切入点b)PointCut 释意:切入点集合是com.xyz.someapp.service.下面的任何类,任何方法,任何返回值的一个切入点的集合。
最全面的Spring学习笔记
最全⾯的Spring学习笔记致⼒于提供⼀种⽅法管理你的业务对象。
在⼤量Java EE的应⽤中,随处可见Spring。
今天我将简单的介绍⼀下Spring这个框架。
本⽂适合读者:想学Spring的Java开发者刚⽤Spring不久的⼈Why为什么要使⽤Spring?Spring主要两个有功能为我们的业务对象管理提供了⾮常便捷的⽅法:DI(Dependency Injection,依赖注⼊)AOP(Aspect Oriented Programming,⾯向切⾯编程)Java Bean每⼀个类实现了Bean的规范才可以由Spring来接管,那么Bean的规范是什么呢?必须是个公有(public)类有⽆参构造函数⽤公共⽅法暴露内部成员属性(getter,setter)实现这样规范的类,被称为Java Bean。
即是⼀种可重⽤的组件。
DI-依赖注⼊简单来说,⼀个系统中可能会有成千上万个对象。
如果要⼿⼯维护它们之间的关系,这是不可想象的。
我们可以在Spring的XML⽂件描述它们之间的关系,由Spring⾃动来注⼊它们——⽐如A类的实例需要B类的实例作为参数set进去。
AOP-⾯向切⾯编程就以⽇志系统为例。
在执⾏某个操作前后都需要输出⽇志,如果⼿⼯加代码,那简直太可怕了。
⽽且等代码庞⼤起来,也是⾮常难维护的⼀种情况。
这⾥就需要⾯向切⾯来编程How关于BeanBean的⽣命周期如你所见,在bean准备就绪之前,bean⼯⼚执⾏了若⼲启动步骤。
我们对图进⾏详细描述:1. Spring对bean进⾏实例化;2. Spring将值和bean的引⽤注⼊到bean对应的属性中;3. 如果bean实现了BeanNameAware接⼝,Spring将bean的ID传递给setBean-Name()⽅法;4. 如果bean实现了BeanFactoryAware接⼝,Spring将调⽤setBeanFactory()⽅法,将BeanFactory容器实例传⼊;5. 如果bean实现了ApplicationContextAware接⼝,Spring将调⽤setApplicationContext()⽅法,将bean所在的应⽤上下⽂的引⽤传⼊进来;6. 如果bean实现了BeanPostProcessor接⼝,Spring将调⽤它们的post-ProcessBeforeInitialization()⽅法;7. 如果bean实现了InitializingBean接⼝,Spring将调⽤它们的after-PropertiesSet()⽅法。
Springcloud简单学习总结
Springcloud简单学习总结微服务简介⼀、spring boot和spring cloud 的关系spring boot来写各个拆分出来的微服务,spring cloud把各个微服务联系起来,⽐如各个微服务通过eurke找到对⽅spring cloud还提供很多微服务解决⽅案,⽐如⽹关、安全、熔断降级⼆、如何来设计微服务1.服务拆分2.服务注册:⼀个单体架构拆分成多个微服务之后,⼀个服务怎么知道另⼀个服务的存在呢,或者怎么找到另⼀个服务,就需要服务注册3.服务发现:需要找到另⼀个服务的时候,可以通过服务的名称去调⽤另⼀个服务4.服务消费(feign或者ribbon实现):A服务区调⽤B服务, A服务就是消费者,服务被称为提供者5.统⼀⼊⼝(API⽹关实现)服务数量多起来之后肯定难管理,不可能去获知到每⼀个服务,虽然可以通过服务名称来调⽤,这样服务的消费者需要记住很多服务的名称话很⿇烦这就需要⼀个统⼀的⼊⼝,只需要知道这个⼊⼝的名称就可以了,不需要具体的知道每⼀个服务提供者的名称6.配置管理(config或者Apollo实现):配置⽂件管理平台7.熔断机制(hystrix实现):系统在⾼并发的可能会响应不过来,这时候就需要熔断机制,把所有请求都挡住,防⽌系统崩溃;通过熔断系统,把请求挡住,返回⼀个默认的值8.⾃动扩展:服务能⾃动扩容.三、拆分⽅法1.拆分⽅法⽤户界⾯层应⽤层领域层基础设施层天⽓预报系统架构设计1.拆分后的每个微服务的名称msa-weather-collection-servermsa-weather-data-servermsa-weather-city-servermsa-weather-report-server2.天⽓预报系统每个微服务作⽤1)天⽓数据来⾃于第三⽅的数据接⼝,通过"天⽓数据采集微服务"采集过来存储到redis2)所有城市数据列表存储在xml⽂件,通过"城市数据API微服务"来解析,并提供相应接⼝给:天⽓数据采集微服务(根据"城市数据列表微服务"去采集该城市的数据,⽐如去采集⼴州的数据)天⽓预报微服务,因为天⽓预报微服务需要提供下拉框来选择不同的城市,展⽰天⽓情况3)"天⽓数据API微服务"数据来源是从redis中获取的,数据提供给"天⽓预报微服务"来展现3.天⽓预报系统⼯作流程1).天⽓数据采集微服务通过调⽤"城市数据API微服务"获得该城市的ID或者Name,去采集该城市的天⽓数据存储到redis2).天⽓预报微服务通过调⽤"城市数据数据API"获得该城市ID或者Name,在调⽤"天⽓数据API微服务"去采集该城市的天⽓数据,然后展现在web页⾯4.天⽓预报系统接⼝设计第三放天⽓接⼝ GET /weather_mini?citykey={cityId} 参数:cityId天⽓数据接⼝ GET /weather/cityId/{cityId} 参数cityId为城市ID GET /weather/cityName/{cityName} 参数cityName为城市名称天⽓预报接⼝ GET /report/cityId{cityId} 参数:cityId为城市ID城市数据接⼝ GET /cities系统存储是redis和XML(城市的列表)spring cloud简介1.spring cloud作⽤提供配置管理服务注册,作为服务的管理者,他要了解这些服务的状况,让每个服务都注册到spring cloud中,跟它有交互服务发现:不同服务之间能够互相发现对⽅,通过服务注册表和服务注册中⼼实现,发现之后才能调⽤对⽅断路器:当系统负载过⼤的时候它会掐断访问负载均衡、智能路由、微代理、服务间调⽤、⼀次性令牌、控制总线、全局锁、领导选举、分布式会话、集群状态、分布式消息2.spring cloud⼦项⽬介绍1)spring cloud config 配置中⼼,把配置利⽤git来集中管理程序的配置,客户端去读git中的配置2)spring cloud netflix 集群众多netflix的开源软件,包括:Eureka、hystrix、zuul、archaius3)spring cloud bus 消息总线,利⽤分布式消息将服务和服务实例连接在⼀起,⽤于在⼀个集群中传播状态的变化,⽐如配置更改的事件. 可与spring cloud config联合实现热部署 其实就是通信⽅式4)spring cloud cluster 基于zookeeper、redis、hazelcast、consul等实现的领导选举和平民状态模式的实现5)spring cloud consul 实现服务发现和配置管理6)spring cloud security 在zuul代理中为oauth2 rest客户端和认证头转发,提供负载均衡7)spring cloud sleuth 适⽤于spring cloud应⽤程序的分布式跟踪,与zipkin、htrace和基于⽇志(例如ELK)的跟踪相兼容.可以做⽇志收集8)spring cloud data flow 云本地编排服务.易于使⽤的DSL、拖放式GUI和REST API⼀起简化了基于微服务的数据管道的整体编排9)spring cloud stream ⼀个轻量级的事件驱动的微服务框架来快速构建可以连接到外部系统的应⽤程序.使⽤kafka或者rabbitmq在spring boot应⽤程序之间发送和接收消息的简单声明模型10)spring cloud connectors 便于paas应⽤在各种平台上连接到后端,例如数据可和消息服务服务发现和注册1.微服务发现的意义你发布的服务要让其他的服务找到2.如何发现服务通过URI访问访问服务通过服务名称访问 1)10.2.3.1:8080的java服务注册到Eureka中叫passport,10.2.3.2:8080的java服务注册到Eureka中叫passport 2)现在Eureka中passport服务后对应的是10.2.3.1:8080和10.2.3.2:8080的java的服务提供服务 3)然后10.2.3.3:8090服务通过访问passport这个服务名访问到10.2.3.1:8080或者10.2.3.2:8080,不⽤记IP地址+端⼝访问了 4)假如把10.2.3.2:8080服务迁移到10.2.3.4中,那么只需要将3.4注册到Eureka的passport服务中, 10.2.3.3就不⽤更改代码了3.如何搭建Eureka server1)创建⼀个spring cloud项⽬2)pox.xml引⼊eureka-server包3)在配置⾥设置监听端⼝,启动server功能,关闭client功能4.如何把服务注册进Eureka2)创建⼀个spring cloud项⽬2)引⼊eureka-client包3)在代码⾥加上@EnableDisCoveryClient 就可以被eureka⾃动发现了4)在application.properties配置⽂件⾥加上如下内容 : passport #注册到eureka server的服务名称 eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka/ #eureka的server地址微服务消费者1.微服务消费模式1)服务直连模式,直接通过域名或者路径访问2)客户端发现模式,服务实例启动后,将⾃⼰的位置信息提交到注册中⼼;客户端从注册中⼼查询,来获取可⽤的服务实例;客户端⾃⾏使⽤负载均衡算法从多个实例中选择出⼀个3)服务端发现模式,跟客户端发现模式唯⼀的区别,就是负载均衡不是客户端来做的,是服务端做的架构见图2.常见微服务消费者1)httpClient2)ribbon 基于客户端的负载均衡,结合eureka,使⽤⽀持http和tcp来实现客户端的负载均衡,Eureka为微服务实例提供服务注册,Robbon作为服务消费的客户端; Ribbon使⽤⽅法 添加依赖 dependencies { compile('org.springframework.cloud:spring-clou-starter-netflix-ribbon') } 注⼊ 加⼊:@RibbonClient(name="Ribbon-client",configuration = RibbonConfiguration.class) 配置 LB的算法等等 使⽤ restTemplate.getForEntity("http://passport/cities",String.class) #直接通过注册到eureka的服务名+路径调⽤.原来是10.2.3.1:8080/cities3)feign #这个最常⽤ ①pox. 中添加feign依赖 ②在Application.java启动类中添加@EnableFeignClientsAPI⽹关1.作⽤:统⼀服务⼊⼝,可以⽅便的实现对平台众多服务接⼝进⾏管控,对访问的⽤户⾝份进⾏验证,防⽌数据篡改,业务功能的鉴权,响应数据的脱敏,流量和并发的控制2.API⽹关的意义 集合多个API,对多个API进⾏管理 统⼀API⼊⼝3.API⽹关的好处避免将内部信息泄露给外部,能够将外部公共API跟内部的微服务的API区分开(外部就是给Android之类的调⽤,内部就是给微服务之间调⽤)为微服务添加额外的安全层:为全部的微服务提供统⼀的⼊⼝,从⽽避免的外⾯客户进⾏服务发现和版本控制时都没有授权的API进⾏访问⽀持混合通信协议降低构建微服务的复杂性微服务模拟与虚拟化,通过将微服务内部的API和外部的API加以区分4.API⽹关弊端路由逻辑配置要进⾏统⼀管理,这样才能保证合理的路由连接API⽹关需要做⾼可⽤5.常见API⽹关实现⽅法Nginxspring cloud zuulKONG6.如何集成zuul功能:认证、压⼒测试、⾦丝雀测试、动态路由、负载削减、安全、静态响应处理、主动交换管理1)在controller中引⼊zuul,@EnableZuulProxy2)在application.properties中写⽅法,⽐如zuul.routes.path: /hi/**, zuul.routes.hi.serviceId:passport,就是访问zuul的时候,只要是/hi这个路径的,就将请求转发给passport微服务处理微服务的集中化配置⼀、为什么需要集中化配置微服务数量多,配置多;⼀个微服务需要部署到多台机器,各⾃有不同的配置⼿⼯管理配置繁琐⼆、集中化配置按什么分类1.按照配置的来源划分 主要有源代码、⽂件、数据库连接、远程调⽤等2.按照配置的环境划分 开发环境、测试环境、预发布环境、⽣产环境3.按照配置的集成阶段划分 编译时:源代码级别的配置;把源代码和编译⽂件⼀起提交到代码仓库 打包时:打包阶段通过某种形式将配置⽂件打⼊到最终的应⽤中 运⾏时:应⽤在启动前不需要知道具体的配置,在启动的时候就可以在本地或者远程获取配置⽂件4.按照配置的加载⽅式划分 启动加载: 应⽤在启动时获取配置,并且是只获取⼀次,在应⽤起来之后就不会再去加载配置了(⽐如端⼝号,线程池的信息,基本上⼀启动就不会变) 动态加载: 应⽤在运⾏的各个过程中随时都可以获取到的⼀些配置;这些配置意味着在应⽤运⾏过程中可能会被经常的修改(⽐如页⾯中分页的⼤⼩,⽐如从⼀页20,改为⼀页30,改完就会⽣效的)三、配置中⼼的要求1.⾯向可配置的编码,提取出来,不能写死 ⽐如页⾯分页的⼤⼩,数据库的连接池2.隔离性 不能的部署环境,应⽤之间的配置要隔离,⽐如⽣产环境⼀个配置,测试环境⼀个配置3.⼀致性 同个微服务,如果要部署在多台机器上做分布式,要使⽤同⼀个配置4.集中化配置 在分布式环境下应⽤的配置应该要具备可管理性;配置可以被远程管理四、spring cloud config架构config server:基于git,所以能轻松的实现标记版本的配置环境(可以实现环境+版本的区分),可以访问管理内容config client:五、如何集成spring cloud config1.配置config server添加依赖: dependencies {compile('org.springframe.cloud:spring-cloud-config-server')}引⼊config server注解:@EnableConfigServer修改application.properties: micro-weather-config-server #服务名称server.port=8888eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka #注册到eureka-serverspring.cloud.config.server.git.uri=https:///waylau/spring-cloud-microservice-development #指定git地址spring.cloud.config.server.git.searchPaths=config-repo #指定git下⾯的路径,跟上⾯合起来就是https:///waylau/spring-cloud-microservice-development/config-repo 2.配置config client添加依赖 dependcies { compile('org.springframe.cloud:spring-cloud-config-client') }修改application.properties: passport #服务名称eureka.client.serviceUrl.defaultZone: http://localhost:8761/eureka #注册到eureka-serverspring.cloud.config.profile=dev #指定环境spring.cloud.config.uri= http://localhost:8888 #指定config server地址#### https:///waylau/spring-cloud-microservice-development⽬录下有个配置⽂件叫passport-dev.properties,内容如下auther=mayun #指定⼀个作者名字3.配置⽂件命名规则{application—name}-{profile}.properties⽐如:passport-dev.properties那passport微服务怎么找到这个配置⽂件呢就是通过application.properties中的服务名称-环境(passport-dev)去config server中application.properties中定义的地址⾥去找passport-dev.properties4.让passport去调⽤远程配置⽂件写⼀个测试⽤例public class ApplicationTests {@Value("${auther}")@Testpublic void contextLoads() {assertEquals("mayun",auther) #如果配置⽂件中的auther的值跟我定义的"mayun"相等,那么就是读取到了}}服务的熔断降级1.什么是服务的熔断机制如果突然间访问量过⼤,超过我们的承受能⼒,就需要熔断机制,不⾄于让我们的资源耗尽,我们⼜要做响⼜要做防护,就靠熔断机制⽐如访问量突然过⼤,超过我们的承受能⼒(设置阈值),就返回给⽤户⼀个默认值(⽐如错误页⾯之类的)2.熔断的原理就是断路器3.断路器的模式1)微软的⽅案close(关闭) Half-open(半打开) open(打开)如果服务正常的时候,断路器默认是close的,如果请求过来失败的次数超过定义的阈值,会启动⼀个定时器,这段时间断路器是half-open(给系统处理问题的时候),如果超过这个定时器,断路器就会完全打开,给请求的⽤户返回⼀个⾃定义的默认值2)spring cloud hystrix⽅案如果某个服务崩了不正常了,不能提供正常响应的,这时候就会启⽤⼀个断路器,把该服务的响应断开,这时候就有⼀个Fallback,返回⼀个错误信息给⽤户4.熔断的意义好处:系统稳定:如果服务崩了,可以快速给⽤户返回⼀个响应,⽽不是让这个访问等待超时减少性能损耗:如果服务崩了,直接返回⼀个简单的响应内容给⽤户,让⽤户知道服务挂了,⽽不是⼀直重试占⽤系统资源及时响应:阈值可定制:⽐如请求数超过1W就启⽤熔断器,功能:异常处理:例如应⽤程序会暂时的降级,然后调⽤备选的操作,来尝试相同的任务或者获取相同的数据,或者将这个应⽤通知给⽤户,让他稍后再试⽇志记录:断路器能记录失败的请求数,以便管理者能测试失败的操作:⼿动复位:并发:熔断器可以被⼤量并发访问,⼤量请求过来后导致服务⽆法响应,这时候才启⽤熔断,这时候所以的请求都是被熔断器处理了,所以熔断器需要能抗住⼤量并发加速断路:重试失败:把失败的详细信息记录下来,在系统恢复正常的时候,在重试⼀下失败的请求,就是把流量copy下来,在系统恢复正常之后在重试5.熔断与降级的区别熔断器是⽐如某个微服务故障了就会触发熔断操作降级就是,原本每天有100个请求,现在每天只有50个请求,那么就会降低⼀个服务数量6.如何集成hystrix在spring cloud中hystrix会监控微服务的调⽤状况,当失败的调⽤达到⼀定的阈值的时候,就会启⽤熔断机制hystrix有⼀个注解叫做hystrix command,通过这个注解将注解的这个类关联到熔断器连在⼀起的代理上1)开发环境spring cloud starter OpenFeign Finchley.M2spring cloud starter Netflix Hystrix Finchley.M22)创建熔断器(添加hystrix依赖)3)启⽤熔断器(加上注解)3)在controller中加⼊HystrixCommand注解。
JavaSpringBoot如何使用IdentityServer4作为验证服务器学习笔记
上面的 ApiNameSecretbase64 的功能是读取配置中的信息,返回编码好的 Api Name 和 Secret, 下面是我application.properties相关的配 置,同样这些配置需要放到IdentityServer那边,可以是通过内存的方式也可以是通过像我一样使用 UI管理界面直接添加:
JavaSpringBoot如何使用 IdentityServer4作为验证服务器学习笔 记
这边记录下如何使用IdentityServer4 作为 Java SpringBoot 的 认证服务器和令牌颁发服务器。本人也是新手,所以理解不足的地方请多多指教。另外由于真的 很久没有写中文了,用词不太恰当的地方也欢迎新手大佬小伙伴指出,一起进步。另外这边令牌的获取需要手动使用postman根据令牌端点获取,然后放在请求 头里面通过postman发给Java的demo,本身这个demo没有取令牌的功能,请各位注意。
#IdentityServer4 配置文件参数 = Api1 api.secret=secreta
由于没有客户端,这边用postman代替求取token,使用http://x.x.x.x:5000/connect/token,然后给我们的java程序发起请求。
Spring系列之Spring常用注解总结
Spring系列之Spring常⽤注解总结Spring系列之Spring常⽤注解总结传统的Spring做法是使⽤.xml⽂件来对bean进⾏注⼊或者是配置aop、事物,这么做有两个缺点:1、如果所有的内容都配置在.xml⽂件中,那么.xml⽂件将会⼗分庞⼤;如果按需求分开.xml⽂件,那么.xml⽂件⼜会⾮常多。
总之这将导致配置⽂件的可读性与可维护性变得很低。
2、在开发中在.java⽂件和.xml⽂件之间不断切换,是⼀件⿇烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引⼊了注解,通过"@XXX"的⽅式,让注解与Java Bean紧密结合,既⼤⼤减少了配置⽂件的体积,⼜增加了Java Bean的可读性与内聚性。
不使⽤注解:先看⼀个不使⽤注解的Spring⽰例,在这个⽰例的基础上,改成注解版本的,这样也能看出使⽤与不使⽤注解之间的区别,先定义⼀个⽼虎:package com.spring.model;public class Tiger {private String tigerName="TigerKing";public String toString(){return "TigerName:"+tigerName;}}再定义⼀个猴⼦:package com.spring.model;public class Monkey {private String monkeyName = "MonkeyKing";public String toString(){return "MonkeyName:" + monkeyName;}}定义⼀个动物园:package com.spring.model;public class Zoo {private Tiger tiger;private Monkey monkey;public Tiger getTiger() {return tiger;}public void setTiger(Tiger tiger) {this.tiger = tiger;}public Monkey getMonkey() {return monkey;}public void setMonkey(Monkey monkey) {this.monkey = monkey;}public String toString(){return tiger + "\n" + monkey;}}spring的配置⽂件这么写:<?xml version="1.0" encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:p="/schema/p"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-3.0.xsd/schema/context/schema/context/spring-context-3.0.xsd"><bean id="zoo" class="com.spring.model.Zoo"><property name="tiger" ref="tiger"/><property name="monkey" ref="monkey"/></bean><bean id="tiger" class="com.spring.model.Tiger"/><bean id="monkey" class="com.spring.model.Monkey"/></beans>测试⽅法:public class TestAnnotation {/*** 不使⽤注解*/@Testpublic void test(){//读取配置⽂件ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext2.xml");Zoo zoo=(Zoo) ctx.getBean("zoo");System.out.println(zoo.toString());}}都很熟悉,权当复习⼀遍了。
Springcloud学习笔记16-springboot一个项目启动多个实例(调出RunD。。。
3.修 改 配 置 文 件 端 口 、 启 动 即 可
参考文献:
在开发中我们经常需要以不同端口启动同一个项目的多个实例idea中启动多个实例很简单
Springcloud学习笔记 16-springboot一个项目启动多个实例(调出 RunD。。。
在开发中,我们经常需要以不同端口启动同一个项目的多个实例,IDEA中启动多个实例很简单.
1 编辑配置
在项目中,选择Edit Configurations,如下图:
左边选择项目启动类,右边箭头处的勾选去掉即可
2.调出 RunDashboard面板
在项目的文件夹下找到workspace.xml文件
打开,找到RunDashboard节点,添加如下选项,如下
<option name="configurationTypes"> <set> <option value="SpringBootApplicationConfigurationType" /> </set>
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
或者是:<property name="car">
<ref bean="car2"Fra bibliotek>
<constructor-arg value="ad" ></constructor-arg>
<constructor-arg value="sh"></constructor-arg>
<constructor-arg value="300000" index="2"></constructor-arg>
Spring 是一个 IOC(DI) 和 AOP 容器框架.
IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源.
作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件,
</bean>
</property>
集合属性: List
配置 java.util.List 类型的属性, 需要指定 <list> 标签, 在标签里包含一些元素. 这些标签可以通过 <value> 指定简单的常量值, 通过 <ref> 指定对其他 Bean 的引用. 通过<bean>
HelloWord helloWord = (HelloWord) ctx.getBean("helloWord");这种方法基于Bean的Id来获取,使用范围比上面较广
依赖注入的方式 :
Spring 支持 3 种依赖注入的方式
属性注入
构造器注入
工厂方法注入(很少使用,不推荐)
组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接
在applicationContext.xml文件中通过 bean 节点来配置 bean
<constructor-arg value="300000" index="2"></constructor-arg>
</bean>
字面值:
可用字符串表示的值,可以通过 <value> 元素标签或 value 属性进行注入。
</property>
</bean>
内部bean:
<property name="car">
<bean class="com.atguigu.spring.beans.Car">
<constructor-arg value="bc"></constructor-arg>
</bean>
id:Bean 的名称。 在 IOC 容器中必须是唯一的 若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用.
<property name="name" value="王宝强"/
>
</bean>
构造器注入:
通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。(在Java类中,使用ALT+shift+S快速的生成带参的构造函数)
属性注入:
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
属性注入是实际应用中最常用的注入方式
<bean id="helloWord" class="com.atguigu.spring.beans.HelloWord">
FileSystemXmlApplicationContext: 从文件系统中加载配置文件
从 IOC 容器中获取 Bean:
调用 ApplicationContext 的 getBean() 方法——>
HelloWord helloWord = ctx.getBean(HelloWord.class);这种方法基于类型来获取,如果类中有多个相同的bean的名称,这种方法将不在合适
<constructor-arg value="nj"></constructor-arg>
<constructor-arg value="20000" type="double"></constructor-arg>
构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
<bean id="car" class="com.atguigu.spring.beans.Car">
<property name="age" value="26"></property>
<property name="cars">
<bean id="person3" class="com.atguigu.spring.beans.collection.Person">
<property name="name" value="王宝琳"></property>
<bean id="helloWord" class="com.atguigu.spring.beans.HelloWord">
<property name="name" value="王宝强"/>
<property name="name" value="王宝强"></property>
<property name="age" value="38"></property>
</bean>
如果有多个带参的构造函数,且构造函数的先后顺序的类型一样,系统默认的是applicationContext.xml中最上面的那个,我们可以通过index或者类型来区分重载的构造函数
<bean id="car" class="com.atguigu.spring.beans.Car">
ApplicationContext 的主要实现类: