首页>>后端>>Spring->使用注解 + 反射优化冗余代码【附源码】

使用注解 + 反射优化冗余代码【附源码】

时间:2023-11-29 本站 点击:1

业务场景

假如现在有一个爬虫系统,需要查询航班信息,每次都需要根据参数拼接出请求的url,为了避免反爬,我们需要模拟真实的用户请求,保持请求url后边跟的参数的顺序不变,最简单的做法就是一个参数一个参数的拼接出请求url,就像这样:

publicStringcreateUrl(FlightInfoflightInfo){Stringurl="/flight/query?"+"org="+flightInfo.getOrg()+"&dst="+flightInfo.getDst()+"&flightDate="+flightInfo.getFlightDate()+"&flightNo="+flightInfo.getFlightNo()+"&passengerNum="+flightInfo.getPassengerNum();returnurl;}@DatapublicclassFlightInfo{privateStringorg;//出发机场privateStringdst;//到达机场privateStringflightDate;//航班日期privateStringflightNo;//航班号privateintpassengerNum;//乘客数}

这种方式,如果参数多的话,会非常麻烦,代码可读性也非常差。有没有什么优化方法呢?

使用注解 + 反射优化代码

先定义注解

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Inheritedpublic@interfaceFlightQuery{Stringdesc()default"";Stringurl()default"";}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@Documented@Inheritedpublic@interfaceFlightQueryField{Stringname()default"";intorder()default-1;}

作为请求参数的实体类,就变成这样了

@FlightQuery(url="/flight/query",desc="查询航班")@DatapublicclassFlightInfo{@FlightQueryField(name="org",order=1)privateStringorg;//出发机场@FlightQueryField(name="dst",order=2)privateStringdst;//到达机场@FlightQueryField(name="flightDate",order=3)privateStringflightDate;//航班日期@FlightQueryField(name="flightNo",order=4)privateStringflightNo;//航班号@FlightQueryField(name="passengerNum",order=5)privateintpassengerNum;//乘客数}

然后使用反射配合注解的方式,实现接口参数的动态组装,方法参数上你完全可以是其他实体类,比如登陆、下单,其思路都是一样的。

publicstaticStringcreateUrl(FlightInfoflightInfo){FlightQueryflightQuery=flightInfo.getClass().getAnnotation(FlightQuery.class);StringBuilderstringBuilder=newStringBuilder(flightQuery.url());Arrays.stream(flightInfo.getClass().getDeclaredFields()).filter(x->x.isAnnotationPresent(FlightQueryField.class)).sorted(Comparator.comparing(x->x.getAnnotation(FlightQueryField.class).order())).peek(x->x.setAccessible(true)).forEach(field->{FlightQueryFieldflightQueryField=field.getAnnotation(FlightQueryField.class);Objectvalue="";try{value=field.get(flightInfo);}catch(IllegalAccessExceptione){e.printStackTrace();}if(flightQueryField.order()==1){stringBuilder.append("?").append(flightQueryField.name()+"="+value).append("&");}else{stringBuilder.append(flightQueryField.name()+"="+value).append("&");}});returnstringBuilder.toString().substring(0,stringBuilder.toString().length()-1);}publicstaticvoidmain(String[]args){FlightInfoflightInfo=newFlightInfo();flightInfo.setOrg("beijing");flightInfo.setDst("shanghai");flightInfo.setFlightDate("2021-10-01");flightInfo.setFlightNo("CA9988");flightInfo.setPassengerNum(1);System.out.println(createUrl(flightInfo));}

输出如下:

总结:

通过反射来动态获得实体对象上的注解信息,在运行时组装出请求url,这样代码看起来直观很多,而且灵活很多,如果需要url参数有变化,只需要在实体类上修改相关的注解即可,不用修改具体的拼装url的代码。

注解与反射的组合常常是优化代码的利器,可以使代码变得更简洁,可扩展性更好。本文的例子比较简单,只是起一个抛砖引玉的作用,重要的是介绍一种优化代码的思路方法。

END


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/288.html