前言 由于现在开发中使用注解的比较多,下面演示示例以注解为主 SpringBoot 基于 Spring 开发。继承了Spring框架原有的优秀特性和 Spring 框架紧密 结合进一步简化了Spring应用的整个搭建和开发过程。其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。大部分的 SpringBoot 应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。  
springboot基础 springboot的默认结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 src   └── main        ├── java        │   └── com        │       └── example        │           └── demo        │               ├── config        │               ├── controller        │               ├── model        │               ├── service        │               └── DemoApplication.java        ├── resources        │   ├── application.properties//全局的配置文件        │   ├── static        │   ├── templates//spring默认视图路径以 /templates/ 为前缀,以 .html 为后缀        │   └── ...        └── ... 生成的classes目录中com与resources下的子文件平行 
 
主程序类 @SpringBootApplication ,它是一个复合注解。可以用下面三个代替
@SpringBootConfiguration 通过@Configuration 与@Bean结合,注册到Spring ioc 容器。 
@ComponentScan  通过范围扫描的方式,扫描特定注解类,将其注册到Spring ioc 容器。如果不写则扫描@SpringBootApplication注解的所在的包及其下级包 
@EnableAutoConfiguration 通过spring.factories的配置,来实现bean的注册到Spring ioc 容器。 
 
全局的配置文件 配置文件可以是端口配置,数据库设计,日志设计  application.properties  语法结构 :key=value  server.port=8081
 application.yml  语法结构 :         server:           port: 8081
配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Configuration(proxyBeanMethods = false)  public  class  MyConfig   {         @Bean       public  User user01 ()  {         User zhangsan = new  User("zhangsan" , 18 );                  zhangsan.setPet(tomcatPet());         return  zhangsan;     }     @Bean("tom")      public  Pet tomcatPet ()  {         return  new  Pet("tomcat" );     } } 
 
路由设计 SpringMVC @Component:注解是一个通用的注解,被Spring容器扫描并纳入管理,下面三个可以看作其的具体划分 @Controller:修饰web层的类 @Service:修饰service层的类 @Repository:修饰dao层的类
1 2 3 4 5 6 7 8 9 10 11     <context:component-scan  base-package ="com.ssl.controller" />           <mvc:default-servlet-handler />           <mvc:annotation-driven />           <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver"  id ="internalResourceViewResolver" >          <property  name ="prefix"  value ="/WEB-INF/jsp/"  />          <property  name ="suffix"  value =".jsp"  />      </bean >  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Controller @RequestMapping("/controller") public  class  HelloController   {         @GetMapping("/hello")      @ResponseBody       public  String hello (User user)   {                return  user.getDepartment().getName1().contains("njust" );     } 
 
Interceptor 自定义拦截器必须实现HandlerInterceptor接口或者继承Handler InterceptorAdapter类,功能与Servlet Filter类似
1 2 3 4 5 6 7 8 9 public  interface  HandlerInterceptor   {return  false 不放行,不会执行controller中的方法    boolean  preHandle (HttpServletRequest var1, HttpServletResponse var2, Object var3)  throws  Exception ;     void  postHandle (HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4)  throws  Exception ;     void  afterCompletion (HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4)  throws  Exception ; } 
 
Swagger2 不同与Structs框架,springmvc的路由多有注解实现,不便于通用管理,于是需要有一个维护接口的组件 ,swagger应用而生,它可以快速帮助我们编写最新的API接口文档,从而提升了团队开发的沟通效率。
创建Swagger配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Configuration  @EnableSwagger2 @Profile({"dev", "test"}) public  class  Swagger2Api   {      @Bean      Docket createApi ()   {         Docket build = new  Docket(DocumentationType.SWAGGER_2)                 .apiInfo(getApiInfo())                 .select()                 .apis(RequestHandlerSelectors.basePackage("com.wenbin.springboot" ))                 .paths(PathSelectors.any())                 .build();         return  build; 
 
在要分析的control类前加上一下注释
1 2 3 4 @Api(value = "helloController的api文档",description = "helloController的api文档2")  @ApiOperation(value = "hello的入口方法,基本数据类型参数")  @ApiParam(name = "name", value = "姓名",required = true) @ApiImplicitParam(name = "id",value = "用户id",paramType = "path",dataType = "Long",required = true) 
 
访问http://localhost:8080/swagger-ui.html即可看到分析页面
上线系统时,修改application.yml文件防止不必要的信息泄露
1 2 3 4 spring:      profiles:      active:  dev  
 
spring的编程设计 spring有两个重要的设计思想,分别为控制反转(IOC) ,面向切面编程(AOP) 
ioc IoC的核心思想是将对象之间的依赖关系 交给容器来管理,通过配置文件(bean)或注解 等方式告诉容器哪些对象需要被创建和注入,容器会根据配置信息自动创建对象,并将依赖注入到相应的位置。这样可以降低对象之间的耦合度 (两个子系统或类之间的关联程度),提高代码的可维护性和可扩展性。 IOC是一种编程思想,由主动的编程 变成被动的接收 。 类似与thinkphp中的利用__call根据类名调用自动加载
依赖注入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public  class  Customer   {    private  String name;     private  int  age;     public  void  setName (String name)   {         this .name = name;     }     public  void  setAge (int  age)   {         this .age = age;     }     @Override      public  String toString ()   {         return  "Customer{"  +                 "name='"  + name + '\''  +                 ", age="  + age +                 '}' ;     } }     <bean id="customerBean"  class  ="com.powernode.spring6.beans.Customer"  p:name="zhangsan"  p:age="20" /> @Test public  void  testP ()  {    ApplicationContext applicationContext = new  ClassPathXmlApplicationContext("spring-p.xml" );     Customer customerBean = applicationContext.getBean("customerBean" , Customer.class);     System.out.println(customerBean); } public  class  MyTime   {    private  int  year;     private  int  month;     private  int  day;     public  MyTime (int  year, int  month, int  day)   {         this .year = year;         this .month = month;         this .day = day;     }     @Override      public  String toString ()   {         return  "MyTime{"  +                 "year="  + year +                 ", month="  + month +                 ", day="  + day +                 '}' ;     } }     <bean id="myTimeBean"  class  ="com.powernode.spring6.beans.MyTime"  c:_0="2008"  c:_1="8"  c:_2="8" /> 
 
使用注解实现自动装配 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Repository("userDao") public  class  UserDaoImpl  implements  UserDao   {	@Value("李四")  	private  String name; 	@Override  	public  void  save ()   { 		 		System.out.println("DAOImpl保存用户的方法执行了。。。。"  + name); 	} } @Service("UserService")  						 public  class  UserServiceImpl  implements  UserService   {	 	@Autowired  	private  UserDao userDao; 	      	 	      	@Override  	public  void  save ()   { 		 		System.out.println("UserServiceImpl执行了" ); 		userDao.save(); 	} } 
 
AOP AOP可以让开发者在不修改原代码的情况下,在程序执行过程中插入一些行为,从而实现某些横向功能的需求 这个类似与thinkphp中的hook,servlet的fliter,常用于日志,行为检测,插件开发等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public  class  DiyPointCut   {    public  void  before ()  {         System.out.println("======方法执行前======" );     }     public  void  after ()  {         System.out.println("======方法执行后======" );     } } <aop:pointcut id="point"  expression="execution(* com.kuang.service.UserServiceImpl.*(..))" /> <aop:before method="before"  pointcut-ref="point" /> <aop:after method="after"  pointcut-ref="point" /> @Aspect  public  class  AnnotationPointCut   {    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")      public  void  before ()  {         System.out.println("====方法执行前====" );     }     @After("execution(* com.kuang.service.UserServiceImpl.*(..))")      public  void  after ()  {         System.out.println("====方法执行后====" );     } } 
 
Spring Boot actuator Actuator 是 springboot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看、统计等。
编写配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 management:      server:      port:  8080    endpoints:      web:        exposure:                   include:  "*"               base-path:  /actuator    endpoint:      shutdown:        enabled:  true       health:        show-details:  always   
 
端点总结 Spring Boot 1.x 版本的 Actuator 端点在根 URL 下注册 Spring Boot 2.x 版本的 Actuator 端点移动到 /actuator/ 路径下 Spring Boot < 1.5 默认未授权访问所有端点; Spring Boot >= 1.5 默认只允许访问 /health 和 /info 端点
1 2 3 4 5 6 7 8 9 10 /actuator/env	     露出Spring的属性的各种环境变量 /actuator/refresh    通过调用这个端点来更新应用中的配置属性,而不需要重启应用 /actuator/restart     /actuator/heapdump	 返回的 GZip 压缩 堆转储文件,可使用 Eclipse MemoryAnalyzer 加载,通过站点泄露的内存信息,有机会查看到后台账号信息和数据库账号等 /actuator/mappings	 显示所有@RequestMapping路径的整理列表 /actuator/httptrace  显示最近的HTTP请求和响应信息,路径包含一些 http 请求包访问跟踪信息,有可能在其中发现内网应用系统的一些请求信息详情、以及有效用户或管理员的 authorization(token、JWT、cookie)等字段 /actuator/info 	     显示任意应用信息,是在配置文件里自己定义的 /actuator/health 	 显示应用健康信息 /actuator/jolokia    通过这个端点,你可以以 JSON 格式与 JMX MBeans 进行交互,从而监控和管理应用程序的各个方面,查看/actuator/jolokia/list 是否存在关键词 
 
Thymeleaf模板引擎 Spring Boot默认是不支持JSP的,而是推荐使用Thymeleaf、Freemarker等模板引擎,默认情况下,如果你添加了 Thymeleaf 或 FreeMarker 的依赖,Spring Boot 将自动配置对应的模板引擎。 SpringBoot默认在static 目录中存放静态资源,而 templates 中放动态页面。 我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。
如果页面是Thymeleaf生成的就会在html上加上这样的标识<html xmlns:th="http://www.thymeleaf.org">
SpEL表达式 使用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public  class  user   {    @Value("${spring.user.username}")      private  String name;     @Value("${spring.user.age} }")          private  Long age; } public  String getindex (Model model)    {    user user1=new  user("bigsai" ,22 );     model.addAttribute("user" ,user1);     return  "index" ;   } <td th:text="${user.name}" ></td>   <td th:text="${user['name']}" ></td> <td th:text="${user.getname()}" ></td> 
 
1 2 3 4 <bean  id ="xxx"  class ="com.java.XXXXX.xx" >          <property  name ="arg"  value ="#{表达式}" >  </bean > 
 
在注解@Value里面
用法 1 2 3 4 5 6     ${} 用于从上下文中获取数据(如模型对象的属性)。     #{} 用于调用 Spring bean 的方法或访问特定功能。     @{} 用于引用外部资源 #{…} 和${…} 可以混合使用,但是必须#{}外面,${}在里面,#{ ‘${}’ } ,注意单引号,注意不能反过来" 基础用法 
 
1 2 3 #{12 *12 } #{T(java.lang.Runtime).getRuntime().exec("calc" )}  #{new  java.lang.ProcessBuilder('cmd' ,'/c' ,'calc' ).start()} 
 
运算符
1 2 3 4 #{my name is+' ' +user} #{shape.kind == 'circle'  and shape.perimeter gt 10000 } #{songSelector.selectSong() == 'May Rain'  ? piano:saxphone} #{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com' } 
 
SpringSecurity Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架 配置类授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @EnableWebSecurity public  class  SecurityConfig  extends  WebSecurityConfigurerAdapter   {    @Override      protected  void  configure (AuthenticationManagerBuilder auth)  throws  Exception  {         auth.                                  inMemoryAuthentication()                                  .withUser("张三" )                                  .password("123456" )                                  .roles("vip1" )                                  .authorities("user:select" ,"user:delete" ,"user:insert" ,"user:update" )                 .and()                 .withUser("李四" )                 .password("123456" )                 .roles("vip2" )                 .authorities("user:select" ,"user:export" );       }     @Override      protected  void  configure (HttpSecurity http)  throws  Exception  {         http.authorizeRequests()                 .antMatchers("/" ).permitAll()                 .antMatchers("/level1/**" ).hasAnyRole("vip1" )                 .antMatchers("/level2/**" ).hasAnyRole("vip2" )                 .antMatchers("/level3/**" ).hasAnyRole("vip3" );         http.csrf().disable();              } } 
 
身份校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17   @GetMapping("info")     public  Authentication info ()  {                  SecurityContext context = SecurityContextHolder.getContext();                  Authentication authentication = context.getAuthentication();         UserDetails principal = (UserDetails) authentication.getPrincipal();         System.out.println(principal.getUsername());         return  authentication;     }  @GetMapping("select")      @PreAuthorize("hasAuthority('user:select')")       public  String select ()  {         System.out.println("查询用户" );         return  "查询用户" ;     } 
 
thymeleaf注入 在<= thymeleaf-spring5:3.0.12 组件中,thymeleaf结合模板注入中的特定场景可能会导致远程代码执行。详细描述参见 https://github.com/thymeleaf/thymeleaf-spring/issues/256 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @RequestMapping("/hello") public  class  HelloController   {  @RequestMapping("/whoami/{name}/{sex}")    public  String hello (@PathVariable("name")  String name,  @PathVariable("sex")  String sex) {    return  "Hello"  + name + sex;   } } @PostMapping("/getNames") public  String getCacheNames (String fragment, ModelMap mmap)  {  mmap.put("cacheNames" , cacheService.getCacheNames());   return  prefix + "/cache::"  + fragment; } 
 
shiro 简单配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [main] shiro.loginUrl  = /login.jsp[users] root  = secret,adminguest  = guest,guest[roles] admin  = *[urls] /user/** = authc /admin/list  = authc, roles[admin] /admin/** = authc /audit/** = authc, perms["audit:list"]   /** = anon