0%

###ribbon负载均衡
必须存在

1
2
3
4
5
@Bean
@LoadBalanced//通过再restTemplate中添加拦截器 实现负载均衡、重写uri等功能
RestTemplate restTemplate(){
return new RestTemplate();
}
阅读全文 »

eureka客户端:

  • 服务注册相关配置 注册的中心、心跳、注册信息缓存时间 org.springframework.cloud.netflix.eureka.EurekaClientConfigBean
  • 服务实列配置信息 服务实列的名称、地址、健康检查路径 org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean
    eureka服务端:
  • 配置相关检测 eureka.server中配置 org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean 服务端相关配置
阅读全文 »

##1:resource接口

Resource是spring 中加载资源的顶级接口 主要方法有:
阅读全文 »

#####jpa扩充jpaRepository接口的方法
1:定义一个接口 继承于 JpaRepository
2:定义接口实现类
3:定义 接口加载工厂方法
4:repository 继承自定义接口
5:启动类使用 自定义加载工厂
####1:定义扩充方法接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 基于jpa的默认jpaRepository实现自己的repository接口
* NoRepositoryBean 不会创建接口的实例 必须要加这个注解
*
* @author ming
* @date 2017-08-28 11点
*/
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {

/**
* 使用原生sql 查询 list列表
*
* @author ming
* @date 2017-08-29 16点
*/
List<T> findListByNativeSql(String sql, Class<T> clzss);
}
阅读全文 »

####全局异常处理
在web中 异常也分为系统异常和业务异常 可以通过增强控制器 来对异常进行全局处理
1:创建业务异常类

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

import lombok.Data;

import java.util.Map;

/**
* 自定义服务异常
*
* @author ming
* @date 2017-06-24
*/
@Data
public class ServiceException extends RuntimeException {

/**
* 异常编码
*/
private int code;
/**
* 消息
*/
private String msg;
/**
* 扩展参数
*/
private Map<String, Object> extParams;


}

阅读全文 »

####全局处理json数据返回格式
在前后端分离中 前后端为了更好的交互 应该指定一个较为通用的数据返回格式
基本上都是code+data 方式返回
在spring mvc 中通过对controller全局增强 来进行处理

1:制定 返回json数据返回大致格式

阅读全文 »

配置mvc相关参数的类

常用的 也就是如下三种方法 如果需要使用spring boot 中默认实现 请选则第三种方式 避免覆盖spring boot 实现

阅读全文 »

指定前后端传输数据格式

在前后分离项目中 最麻烦的应该就是 前后端工程师对接
后端通过添加mvc消息转换器 返回更加符合前端的数据格式
这个数据格式 不是说返回的格式 而是 某些类型的数据的处理 例如 date 可以转换成Long类型的时间戳返回
直接继承实现即可 如果是继承WebMvcConfigurerAdapter 实现的mvc 相关配置 可以不用管 这样 它自己会添加到转换器链中
如果是继承WebMvcConfigurationSupport 那么 需要重写configureMessageConverters() 手动添加到转换器链中

阅读全文 »

在使用spring 中总有地方要求获取bean或者注册bean 所以找了部分资料 抄袭了几波 合并成如下工具类
主要功能 :

  • 获取bean
  • 手动注册bean
  • 删除手工注册的bean
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    package com.ming.utils;

    import com.google.common.collect.Maps;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;

    import java.lang.annotation.Annotation;
    import java.util.Map;
    import java.util.Set;

    /**
    * 对操作spring applicationcontext提供基本封装 方便使用
    * 使用order 最先加载
    * 预期在容器最开始加载 暂时这个无法生效 如果需要这个bean 优先加载 请调整依赖 来调整bean加载顺序
    *
    * @author ming
    * @date 11:00
    */
    @Component
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class SpringBeanManager implements ApplicationContextAware, DisposableBean {


    /**
    * spring bean上下文
    *
    * @author ming
    * @date 11:00
    */
    private static ApplicationContext applicationContext;
    /**
    * 获取BeanFactory 进行动态注册bean 删除bean
    *
    * @author ming
    * @date 2017-11-10 15:51
    */
    private static DefaultListableBeanFactory defaultListableBeanFactory;

    /**
    * 手动注册的bean 名称列表 必须保证 每个使用它的地方 是一样的
    *
    * @author ming
    * @date 2017-11-10 15:54
    */
    private static volatile Map<String, Class<?>> manualRegisterBeanMap = Maps.newConcurrentMap();


    /**
    * 获取 手动注入的 bean名称
    *
    * @return Set<String>
    * @author ming
    * @date 2017-12-12 13:46
    */
    public static Set<String> getManualRegisterBeanNameSet() {
    return manualRegisterBeanMap.keySet();
    }

    /**
    * 动态注入bean
    *
    * @param beanName
    * @param beanClazz
    * @author ming
    * @date 2017-11-09 16:50
    */
    public static void registerBean(String beanName, Class<?> beanClazz) {
    assert StringUtils.isNotEmpty(beanName);
    assert beanClazz != null;
    checkDefaultListableBeanFactory();
    //创建beanBuilder
    BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz);
    //注册bean
    defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
    //添加手工注册的beanName 到集合
    manualRegisterBeanMap.put(beanName, beanClazz);
    }

    /**
    * 删除bean
    *
    * @param beanName
    * @author ming
    * @date 2017-11-10 15:45
    */
    public static void removeBean(String beanName) {
    assert StringUtils.isNotEmpty(beanName);
    //当试图删除 非手动注册的bean的时候
    if (!manualRegisterBeanMap.keySet().contains(beanName)) {
    throw new UnsupportedOperationException("不能删除非手动注册的bean");
    }
    checkDefaultListableBeanFactory();
    defaultListableBeanFactory.removeBeanDefinition(beanName);
    manualRegisterBeanMap.remove(beanName);
    }

    /**
    * 根据名称 获取bean
    *
    * @param name 注册的bean名称
    * @return T
    * @author ming
    * @date 11:19
    */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
    checkApplicationContext();
    return (T) applicationContext.getBean(name);
    }

    /**
    * 根据类型 获取bean
    *
    * @param clazz 注册bean的类型
    * @return T
    * @author ming
    * @date 11:20
    */
    public static <T> T getBean(Class<T> clazz) {
    checkApplicationContext();
    return applicationContext.getBean(clazz);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
    checkApplicationContext();
    return applicationContext.getBean(beanName, clazz);
    }

    /**
    * 获取application中所有注册的bean 列表
    *
    * @return String[]
    * @author ming
    * @date 2017-08-28 16点
    */
    public static String[] getBeanDefinitionNames() {
    checkApplicationContext();
    return applicationContext.getBeanDefinitionNames();
    }

    /**
    * 统计application中所有bean的数量
    *
    * @return Integer
    * @author ming
    * @date 2017-08-28 17点
    */
    public static Integer getBeanDefinitionCount() {
    checkApplicationContext();
    return applicationContext.getBeanDefinitionCount();
    }

    /**
    * 根据注解获取 beanNameList
    *
    * @param annotation
    * @return String[]
    * @author ming
    * @date 2017-08-28 16点
    */
    public static String[] getBeanNameListByAnnotation(Class<? extends Annotation> annotation) {
    checkApplicationContext();
    return applicationContext.getBeanNamesForAnnotation(annotation);
    }

    /**
    * 根据bean类型获取所有的bean
    *
    * @param clazz
    * @return String[]
    * @author ming
    * @date 2017-08-28 16点
    */
    public static String[] getBeanNamesForType(Class clazz) {
    checkApplicationContext();
    return applicationContext.getBeanNamesForType(clazz);
    }

    /**
    * 根据类型 获取 所有这个类型的bean map 键为bean名字 值为注册的bean
    *
    * @param clazz
    * @return Map
    * @author ming
    * @date 2017-08-28 16点
    */
    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
    checkApplicationContext();
    return applicationContext.getBeansOfType(clazz);
    }

    /**
    * 检测applicationcontext是否可用
    *
    * @author ming
    * @date 2017-08-28 17点
    */
    private static void checkApplicationContext() {
    if (applicationContext == null) {
    throw new NullPointerException("spring applicationContext is null !!!");
    }
    }

    /**
    * 检测 defaultListableBeanFactory
    *
    * @author ming
    * @date 2017-11-10 15:47
    */
    private static void checkDefaultListableBeanFactory() {
    if (defaultListableBeanFactory == null) {
    throw new NullPointerException(" spring defaultListableBeanFactory is null !!!");
    }
    }

    private static void updateApplicationContext(ApplicationContext applicationContext) {
    SpringBeanManager.applicationContext = applicationContext;
    }

    private static void updateDefaultListableBeanFactory(DefaultListableBeanFactory defaultListableBeanFactory) {
    SpringBeanManager.defaultListableBeanFactory = defaultListableBeanFactory;
    }

    /**
    * 销毁方法
    *
    * @author ming
    * @date 2017-08-28 17点
    */
    @Override
    public void destroy() throws Exception {
    updateApplicationContext(null);
    updateDefaultListableBeanFactory(null);
    }

    /**
    * 设置上下文
    *
    * @author ming
    * @date 11:17
    */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    updateApplicationContext(applicationContext);
    //获取 bean factory
    updateDefaultListableBeanFactory((DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory());
    }
    }

阅读全文 »

####thymeleaf
虽然现在大部分项目 更加倾向于前后端分离 但是有时候身为后端工程师 总想手贱写点小东西
但是jsp 又比较老 而且需要web容器支撑 spring boot 支持性太差
所以还是用spring boot 推荐的thymeleaf
可是 jsp中的siteMesh装饰器真的好用 苦于thymeleaf没有这个东西
在国外博客看到别人实现了类似功能 特此写这篇笔记 方便后续查阅
1:建立layout注解
用这个注解标识 那些接口需要被装饰

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

import java.lang.annotation.*;

/**
* 样式装饰器 注解 在controller中注解
*
* @author ming
* @date 2017-08-28 11点
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Layout {
/**
* no layout will be used
*/
String none = "none";
/**
* default layout will be used
*/
String defaultLayOut = "default";

String value() default defaultLayOut;
}

阅读全文 »