spring boot开发心得

类和方法注解

@ResponseBody

在代码里只需返回java对象,@ResponseBody注解会自动转为json字符串,同时设置content-type为application/json。

@RestController和@Controller的区别

@Controller:修饰class,用来创建处理http请求的对象

@RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody默认返回json格式。我们可以通过postman查看返回消息的content-type,发现加了@ResponseBody后,确实从text/plain变为application/json 。

因此:

  1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回html页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是return 里的内容。例如:本来应该到success.jsp页面的,则其显示success.
  2. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。
  3. 如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

@Service+@Controller搭配使用

@Service 常用来标注一个业务模块,该模块以单件形式存在。

@Controller MVC里的控制器。

常用的一个实践是:rest请求在Controller里进行,具体业务则在service里实现,Controller负责将rest请求分发到service接口。下面是一个例子:

@Controller
@Path("/lee/v1/secu/auth")
public class RestAuthService extends AbstractROAService
{
    ...

    @Autowired
    private SecurityModuleItf smi_;
    
    @GET
    public String doGet(@QueryParam("oper") String oper, @QueryParam("roleNames") String roleNames, @QueryParam("roleIds") String roleIds)
    {
        try
        {
            if(!Strings.isNullOrEmpty(roleNames))
            {
                List<String> roleNameLst = Util.fromJson(roleNames, List.class);
                return Util.genResponseJson(smi_.authByRoleNames(oper, roleNameLst), null, null) ;
            }
            ...
        }
        catch(Exception e)
        {
            ...
        }
    }
}

public interface SecurityModuleItf
{
    ...

    boolean authByRoleNames(String oper, List<String> roleNames);
}

@Service
public class SecurityModule implements SecurityModuleItf
{
    ...
}

@RequestMapping注解

参数如下:

value:  指定请求的实际url地址, 比如 /action/info之类。 

method:  指定请求的method类型, GET、POST、PUT、DELETE等 

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html; 

produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回 

params: 指定request中必须包含某些参数值时,才让该方法处理 

headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求 

一个样例:

@RequestMapping(value = "/test", method = RequestMethod.GET, headers="Referer=http://xxx.com/")    
public void testHeaders(@PathVariable String ownerId, @PathVariable String petId) {        
  // implementation omitted    
}  

注意:也可以用GetMapping等简化的注解。

init和fini注解

init:@PostConstruct

fini:@PreDestroy

参数和成员注解

@PathVariable

@PathVaribale 获取url路径中的参数,例如获取

http://localhost:8080/hello/{id}

中的id,可以这样写:

    @RequestMapping(value="/hello/{id}",method= RequestMethod.GET)
    public String sayHello(@PathVariable("id") Integer id){
        return "id:"+id;
    }

@RequestParam

@RequestParam 获取url请求参数的值,例如获取

localhost:8080/hello?id=98

中的id值,可以这样写:

    @RequestMapping(value="/hello",method= RequestMethod.GET)
    public String sayHello(@RequestParam("id") Integer id){
        return "id:"+id;
    }

注意:url里数组的写法:

/lee/comp_mgmt/v1/lib_desc?lib=x1&lib=x2

亦即:同名的key构成一个数组。

代码里这样写:

@GetMapping(value="/lib_desc")
    public String showLibs(@RequestParam("lib") List<String> libNames) {
        Map<String,String> res = compMgmtService.showLibs(libNames);
        return SeDeUtil_Java.toJson(res);
    }

@RequestBody

获得消息体中的json对象。下面例子使用@RequestBody从消息体中分离出SaleInput对象列表:

@PostMapping(value="/send_evt")
    public String sendEvent(HttpServletRequest request, @RequestBody List<SaleInput> objs)
    {
        for (SaleInput o: objs)
        {
            evtFrmSvc.acceptEvent(o);
        }
        return "ok";
    }

@Value注解

有$和#两种注解方式,$主要是配置文件里值的获取,格式为:

${ property : default_value }

#是bean属性的获取,格式为:

#{ obj.property }

如要在未给值时设定默认值,可以这样写:

#{ obj.property ?: default_value }
#{ obj.property ? obj.property : default_value }

上述两种写法的效果是一样的。

需要注意的是,如果是获取一个方法的值时,需要在前面增加@,比如

#{ @obj.getProperty() }

覆盖框架的spring bean定义

要覆盖的bean:

@Slf4j
public class HackDataSourceAliasMapper extends DataSourceAliasMapper {

    public void init() {
        try {
            log.info("HackDataSourceAliasMapper.init()");
            super.init();
        }
        catch (Exception e) {
            log.warn("perish DataSourceAliasMapper failure");
        }
    }

}

实现BeanDefinitionRegistryPostProcessor接口,把老的bean移除,替换成新的bean:

@Component
@Slf4j
public class MyBeanRegPostProc implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        String beanName = "dataSourceAliasMapper";
        log.info("begin to hack bean:{} success", beanName);

        beanDefinitionRegistry.removeBeanDefinition(beanName);

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(HackDataSourceAliasMapper.class);
        beanDefinitionBuilder.setInitMethodName("init");
        beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
        log.info("hack bean:{} success", beanName);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        log.info("postProcessBeanFactory: empty");
    }
}

spring bean后处理的顺序

BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法先于
BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法先于
BeanFactoryPostProcessor接口的postProcessBeanFactory方法

与BeanDefinitionRegistryPostProcessor不同,BeanFactoryPostProcessor甚至可以修改bean实例!

调整bean的加载顺序

使用@DependsOnDatabaseInitialization可在dataSource初始化后立刻做一些事情(springboot2.5引入):

某些众所周知类型的bean(如JdbcOperations)将被排序,以便在数据库初始化之后对它们进行初始化。如果有一个直接使用DataSource的bean,请使用@DependsOnDatabaseInitialization注释它的类或@Bean方法,以确保它也在数据库初始化之后被初始化。

其它情况,若想调整两个bean间的关系,可用@DependsOn;当然,用autowired依赖也是可以的,且更自然。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值