近期学习笔记

2018.10.08
1.自定义事件,一般是继承ApplicationEvent抽象类
2.定义事件监听器,一般是实现ApplicationListener接口
3.配置监听器,启动的时候,需要把监听器加入到Spring容器中
4.发布事件,使用ApplicationContext.publishEvent发布事件

配置监听器
1.SpringApplication.addListeners 添加监听器
2.把监听器纳入到spring容器中管理 @Component
3.使用context.listener.classes配置项配置---写入application.properties
4.使用注解@EventListener,在方法上面加入,且该类需要纳入到spring容器中管理 


2018.10.09
ApplicationContextInitializer 接口是在spring容器执行refreshed之前的一个回调
使用步骤:
1.写一个类,实现ApplicationContextInitializer接口
2.注册ApplicationContextInitializer

注册方法:
1.SpringApplication.addInitializers
2.在配置文件中加入 context.Initializer.classes=com.hikvision.xxxxxx
3.可以通过META-INF/spring.factories机制(listener也适用)

---------------------------
CommandLineRunner 接口是在容器启动成功之后的最后一步回调
使用步骤:
1.写一个类,实现CommandLineRunner接口
2.把该类纳入到spring容器的管理之中
有很多个CommandLineRunner的时候,先执行@Order(值) 值比较小的,不写值则排最后
注意:可以使用注解@Order或者Ordered接口来控制执行顺序
CommandLineRunner的参数是最原始的参数,没有做任何处理
ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步封装

-----------------------------
@SpringBootApplication默认扫描的包的路径是当前包以及子包下面的所有类
可以通过scanBasePackages=""修改这个扫描包的路径
@SpringBootApplication(scanBasePackages = "com.zhanghan.demo",exclude = MyConfig.class)
可以通过exclude = xxx.class 来排除指定的类
或使用excludeName = "com.zhanghan.demo.MyConfig" 根据classname

-----------------------------
app.setBannerMode(Banner.Mode.OFF);
可以取消这个大图标
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
 
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)
 可以在resources目录下新建一个banner.txt,系统会自动取代开机动画
 也可以在application.properties中指定 banner.location=my.txt
 banner.image.location=my.jpg
 
 -----------------------------
 springboot运行流程
 1.判断是否是web环境
 2.加载所有classpath下的META-INFO/spring.factories ApplicationContextInitializer
 3.加载所有classpath下的META-INFO/spring.factories ApplicationListener
 4.推断main方法所在的类
 5.开始执行run方法
 6.设置java.awt.headless系统变量
 7.加载所有classpath下的META-INFO/spring.factories SpringApplicationRunListener
 8.执行所有SpringApplicationRunListener的started方法
 9.实例化ApplicationArguments对象
 10.创建environment
 11.配置environment,主要是把run方法的参数配置到environment
 12.执行所有SpringApplicationRunListener的environmentprepared方法
 13.如果不是web环境,但是是web的Environment,则把这个Environment转换成标准的Environment
 14.输出banner
 15.初始化applicationContext,如果是web环境,则实例化AnnotationConfigEmbeddedWebApplicationContext对象,否则则实例化AnnotationConfigApplicationContext
 
 
 
 
------------------------------------
2018.10.10
application.properties 中可设置
server.port=8081   
server.contextPath=/  这样就是服务器下的路径  
在Controller里,参数接收可以用@RequestParam(value="username",defaultValue="admin",required=false) 表示不是必须
@GetMapping("/display/{fuck}")
    @ResponseBody
    public String display(@PathVariable("fuck") String fuck){
        return fuck;
    }
如上图所示,这样就可以获取url中的变量
@RestController=@Controller+@ResponseBody
--------------------------
application.properties 中可设置
spring.mvc.view.prefix=/123    即是相对于webapp的路径
spring.mvc.view.suffix=.jsp  (可为空)  springboot默认不支持jsp
在springboot中使用jsp,需要另外加入tomcat-embed-jasper的依赖,且不能用@RestController
--------------------------
freemarker模板
也是直接return String 
需要先把jsp的依赖去掉,且不能用@RestController
在pom.xml加入依赖
默认在classpath下的templates
也可以在配置文件中 spring.freemarker.templateLoaderPath=classpath:/xxx (可用逗号隔开)
默认扩展名.ftl  
---------------------------
更换内置服务器tomcat为jetty
先在pom中的starter-web后加入
<exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
再加入jetty的依赖
---------------------------
springboot如何处理静态资源
1.src/main/webapp目录下,就可以直接访问
2.默认的静态资源路径是 /META-INFO/resources/
/resources/
/static/
/public/
四个都是

--------------------------
servlet 的Filter
先implements Filter
重写doFilter方法
在类上加@WebFilter("/*")
在启动类上加入@ServletComponentScan
--------------------------
springboot中使用拦截器
1.写一个拦截器,实现HandlerInterceptor接口
2.写一个类,继承WebMvcConfigurerAdapter,然后重写addInterceptor方法,并使用registry.addInterceptorfangfa 

===============preHandle===============Controller执行之前调用
===============postHandle===============Controller执行之后,页面渲染之前
===============afterCompletion===============一切结束后,一般用于资源清理操作
---------------------------
装配DataSource
1.加入数据库驱动
2.配置文件
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/syn_management
spring.datasource.username=ddl_mgr
spring.datasource.password=hik12345#
#######spring.datasource.type 可以指定具体使用哪种数据源(一共四种:DataSourceConfiguration.枚举)
----------------------------
使用阿里druid
加入maven依赖
写一个类,@SpringBootConfiguration
@ConfigurationProperties(prefix="jdbc.mysql")

private String url;
    private String username;
    private String password;
@Bean
    public DataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);// 用户名
        dataSource.setPassword(password);// 密码
        return dataSource;
    }

----------------------------------
事务(只生效于public)
在启动类上加入@EnableTransactionManagement
然后在事务类上加入@Transactional(rollbackFor = Exception.class,noRollbackFor=xxxx.class)
即可

---------------------
AOP

开发流程
1.加入相应依赖 spring-boot-starter-aop
2.写一个Aspect,封装横切关注点(日志、监控等),需要配置通知(前置通知,后置通知)和切入点(那些包哪些类哪些方法等等)
3.这个aspect需要纳入spring容器管理,加入@Aspect

---------------------------------
springboot微服务

@Transactional注解应用于测试类的方法上的时候,只帮你测通而不会插入真实数据(回滚)。
---------------------------------

@JsonInclude(JsonInclude.Include.NON_NULL)
在model类里面加入,这样为null的字段就不返回了
当然,还可以不加注解,用全局配置:  
jackson:
    default-property-inclusion: non_null

        //TODO 不安全的做法,改进
        这种注释后,可以直接在intellij的控制台找到留下的地方
----------------------------------
使用RestTemplate 进行http请求
String url = "https://www.baidu.com";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url,String.class);
//这里代表是返回一个json字符串


先引入freemarker

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
在controller里返回一个ModelAndView
return new ModelAndView("pay/create")
系统会自动去找templates下的路径  .ftl结尾文件


public ModelAndView create(@RequestParam("orderId")String orderId,
                               @RequestParam("returnUrl") String returnUrl,
                               Map<String,Object> map){
        //1.查询订单
        OrderDTO orderDTO = orderService.findById(orderId);
        if(null==orderDTO){
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        //发起支付
        PayResponse payResponse = payService.create(orderDTO);
        map.put("orderId","111111");

        return new ModelAndView("pay/create",map);
    }
其中map中的属性会注入到模板文件里,用${orderId} 去取得即可
如果是个对象,用${orderId.appId}

-----------------------------------
全局异常处理
写一个类,用@ControllerAdvice修饰
写一个方法,用@ExceptionHandler(value=xxxx.class)修饰
拦截后就可以return new ModelAndView("redirect:.......");

------------------------------------
websocket再看一遍
------------------------------------
springboot优雅使用redis缓存


@RestController
@RequestMapping("/api/")
public class aaController {

    @RequestMapping("aaa")
    @Cacheable( cacheNames="product",key="1234")
    public String fuck() {
        System.out.println("111111111");

        return "2";
    }


    @RequestMapping("fuckyou")
    @CachePut( cacheNames="product",key="1234")
    public String fuckyou() {//注意了,这里cacheput的话,必须返回值一样,返回后会加入缓存
        System.out.println("111111111");

        return "3";
    }

    @RequestMapping("fuckyou")
    @CacheEvict( cacheNames="product",key="1234")
    public void qinghuancun() {
        System.out.println("111111111");//这里与返回值无关,执行完就会清缓存
    }
    
    

}
---------------------
lambda表达式学习


Optional<Integer> optional = stream.filter(i->i<10).findAny();   这里返回了一个optional 此时离结果已经很近了
sout(optional.orElse(-1));   这里代表将结果返回,如果没有结果,那么返回-1,这样会避免空指针异常


经常性的stream和option用完转化为普通变量时,又想进行操作,则可以使用Option.of(xxxx)  Stream.of(xxxx) 则可以继续操作了。

list.stream().collect(Collectors.groupingBy(Dish::getType));会返回一个map,key就是type,value就是符合的list中的元素
对应重载的方法:list.stream().collect(Collectors.groupingBy(Dish::getType),Collectors.counting())
这样key是type,value就是各项数量。非常强大
对应重载的方法:list.stream().collect(Collectors.groupingBy(Dish::getType),Collectors.averageingInt(Dish::getCalories))


集合转各种map:
list.stream().collect(Collectors.toConcurrentMap(Dish::getName,Dish::getCarlories)); key就是name,value就是carlories
集合转各种类型集合
list.stream().collect(Collectors.toCollection(LinkedList::new))
------------------------\
intStream.parallel().filter().sequential().map().parallel().forEach();
这种并不是先转成并行再转串行再转并行,而是一个flag,以最后的flag的值为准
-------------------------
completableFuture.whenComplete((v,t)->{})
这是事件执行完后执行的回调函数,v是返回值,t是异常。
一般而言completableFuture不是new出来的,而是接收一个supplier(也就是返回你需要东西的supplier)


一段经典的高并发多线程查询:
public static void main(String[] args){
        //取得非守护线程池
    ExecutorService executor = Executors.newFixedThreadPool(2,r->{
        Thread t = new Thread(r);
        t.setDaemon(false);
        return t;
    });
    
    List<Integer> productionIDs = Arrays.asList(1,2,3,4,5);//假设前端传来五个productId
    productionIDs.stream().map(i->CompletableFuture.supplyAsync(()->queryProduction(i),executor))//此处模拟按照id一次一次查询数据库
    .map(future->future.thenApply(a->a*100)) //模拟对取出来的数据进行操作
    .map(CompletableFuture::join).collect(Collectors.toList());//这里用join方法等待future跑完,然后汇集
    
    
    
    
    
    
}

---------------------
thenApply(a->axxxxxx)   传入Function,  handle((v,t)->vxxxxxx)比thenApply 多了一个异常处理
whenComplete Consumer
thenRun  可以在complete之后执行的Consumer,注意,这里前面的值不会传进去

汪文君需要把最后那俩api再看看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值