From 161521f8a5e71e1ecdd7979f980a583cd170df72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Mon, 7 Jan 2019 17:15:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A1=B9=E7=9B=AEREADME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- pictures/aop执行顺序.png | Bin 0 -> 14889 bytes pictures/dubbo-ano-common.png | Bin 0 -> 10233 bytes pictures/dubbo-ano-consumer.png | Bin 0 -> 10412 bytes pictures/dubbo-ano-provider.png | Bin 0 -> 9810 bytes pictures/dubbo-common.png | Bin 0 -> 9107 bytes pictures/dubbo-consumer.png | Bin 0 -> 9279 bytes pictures/dubbo-provider.png | Bin 0 -> 10318 bytes pictures/spring-aop-annotation.png | Bin 0 -> 17792 bytes pictures/spring-aop.png | Bin 0 -> 16777 bytes pictures/spring-dubbo-annotation.png | Bin 0 -> 10800 bytes pictures/spring-dubbo.png | Bin 0 -> 9366 bytes pictures/spring-email-annotation.png | Bin 0 -> 15034 bytes pictures/spring-email.png | Bin 0 -> 13920 bytes pictures/spring-memcached-annotation.png | Bin 0 -> 14658 bytes pictures/spring-memcached.png | Bin 0 -> 16218 bytes pictures/spring-mongodb-annotation.png | Bin 0 -> 15583 bytes pictures/spring-mongodb.png | Bin 0 -> 14536 bytes pictures/spring-rabbitmq-annotation.png | Bin 0 -> 19520 bytes pictures/spring-rabbitmq.png | Bin 0 -> 20650 bytes ...结构.png => spring-redis-annotation.png} | Bin ...目目录结构.png => spring-redis.png} | Bin pictures/spring-scheduling-annotation.png | Bin 0 -> 12334 bytes pictures/spring-scheduling.png | Bin 0 -> 14333 bytes pictures/spring-websocket-annotation.png | Bin 0 -> 18931 bytes pictures/spring-websocket.png | Bin 0 -> 18614 bytes spring/spring-aop-annotation/README.md | 169 ++++++++ .../com/heibaiying/advice/CustomAdvice.java | 2 + .../test/java/com/heibaiying/aop/AopTest.java | 2 - spring/spring-aop/README.md | 162 +++++++ spring/spring-dubbo-annotation/README.md | 327 ++++++++++++++ .../config/DispatcherServletInitializer.java | 2 +- .../config/dubbo/DubboConfiguration.java | 17 +- .../heibaiying/controller/SellController.java | 2 +- .../config/dubbo/DubboConfiguration.java | 18 + spring/spring-dubbo/README.md | 279 ++++++++++++ spring/spring-email-annotation/README.md | 287 +++++++++++++ .../com/heibaiying/config/EmailConfig.java | 2 +- spring/spring-email/README.md | 298 +++++++++++++ .../java/com/heibaiying/email/SpringMail.java | 2 +- .../src/main/resources/springApplication.xml | 2 +- .../test/java/com/heibaiying/SendEmail.java | 14 +- spring/spring-memcached-annotation/README.md | 150 +++++++ spring/spring-memcached/README.md | 191 +++++++++ spring/spring-mongodb-annotation/README.md | 161 +++++++ spring/spring-mongodb/README.md | 144 +++++++ .../src/main/resources/mongodb.xml | 5 +- spring/spring-rabbitmq-annotation/README.md | 403 ++++++++++++++++++ .../heibaiying/rabbit/RabbitBaseConfig.java | 2 +- spring/spring-rabbitmq/README.md | 381 +++++++++++++++++ .../rabbit/RabbitBaseAnnotation.java | 5 +- .../com/heibaiying/rabbit/RabbitTest.java | 2 +- spring/spring-redis-annotation/README.md | 2 +- spring/spring-redis/README.md | 2 +- spring/spring-scheduling-annotation/README.md | 192 +++++++++ spring/spring-scheduling/README.md | 183 ++++++++ .../main/java/com/heibaiying/task/Task.java | 3 - spring/spring-websocket-annotation/README.md | 203 +++++++++ .../com/heibaiying/constant/Constant.java | 4 +- .../controller/LoginController.java | 3 +- .../DispatcherServletInitializer.java | 3 +- .../heibaiying/webconfig/ServletConfig.java | 3 +- .../webconfig/characterEncodingFilter.java | 3 +- ...ustomerHandler.java => CustomHandler.java} | 2 +- .../heibaiying/websocket/WebSocketConfig.java | 5 +- spring/spring-websocket/README.md | 233 ++++++++++ .../com/heibaiying/constant/Constant.java | 5 - .../controller/LoginController.java | 2 - ...ustomerHandler.java => CustomHandler.java} | 3 +- .../src/main/resources/springApplication.xml | 4 +- 70 files changed, 3835 insertions(+), 51 deletions(-) create mode 100644 pictures/aop执行顺序.png create mode 100644 pictures/dubbo-ano-common.png create mode 100644 pictures/dubbo-ano-consumer.png create mode 100644 pictures/dubbo-ano-provider.png create mode 100644 pictures/dubbo-common.png create mode 100644 pictures/dubbo-consumer.png create mode 100644 pictures/dubbo-provider.png create mode 100644 pictures/spring-aop-annotation.png create mode 100644 pictures/spring-aop.png create mode 100644 pictures/spring-dubbo-annotation.png create mode 100644 pictures/spring-dubbo.png create mode 100644 pictures/spring-email-annotation.png create mode 100644 pictures/spring-email.png create mode 100644 pictures/spring-memcached-annotation.png create mode 100644 pictures/spring-memcached.png create mode 100644 pictures/spring-mongodb-annotation.png create mode 100644 pictures/spring-mongodb.png create mode 100644 pictures/spring-rabbitmq-annotation.png create mode 100644 pictures/spring-rabbitmq.png rename pictures/{spring+redis+ano项目目录结构.png => spring-redis-annotation.png} (100%) rename pictures/{spring+redis项目目录结构.png => spring-redis.png} (100%) create mode 100644 pictures/spring-scheduling-annotation.png create mode 100644 pictures/spring-scheduling.png create mode 100644 pictures/spring-websocket-annotation.png create mode 100644 pictures/spring-websocket.png create mode 100644 spring/spring-aop-annotation/README.md create mode 100644 spring/spring-aop/README.md create mode 100644 spring/spring-dubbo-annotation/README.md create mode 100644 spring/spring-dubbo/README.md create mode 100644 spring/spring-email-annotation/README.md create mode 100644 spring/spring-email/README.md create mode 100644 spring/spring-memcached-annotation/README.md create mode 100644 spring/spring-memcached/README.md create mode 100644 spring/spring-mongodb-annotation/README.md create mode 100644 spring/spring-mongodb/README.md create mode 100644 spring/spring-rabbitmq-annotation/README.md create mode 100644 spring/spring-rabbitmq/README.md create mode 100644 spring/spring-scheduling-annotation/README.md create mode 100644 spring/spring-scheduling/README.md create mode 100644 spring/spring-websocket-annotation/README.md rename spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/{CustomerHandler.java => CustomHandler.java} (97%) create mode 100644 spring/spring-websocket/README.md rename spring/spring-websocket/src/main/java/com/heibaiying/websocket/{CustomerHandler.java => CustomHandler.java} (94%) diff --git a/README.md b/README.md index 357d076..53b83b1 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ spring-cloud:Finchley.SR2 | [spring-websocket](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-websocket)
[spring-websocket-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-websocket-annotation) | spring 整合 websocket | [Spring Websocket](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web.html#websocket) | | [spring-mail](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-email)
[spring-mail-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-email-annotation) | spring 普通文本邮件、附件邮件、模板邮件 | [Spring Email](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#mail) | | [spring-scheduling](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-scheduling)
[spring-scheduling-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-scheduling-annotation) | spring 定时任务 | [Task Execution and Scheduling](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#scheduling) | -| spring-kafka
spring-kafka-annotation | spring 整合 kafka | [Spring for Apache Kafka](https://docs.spring.io/spring-kafka/docs/2.2.2.RELEASE/reference/html/) |
@@ -86,4 +85,5 @@ spring-cloud:Finchley.SR2 代码涉及到的相关参考资料放在了仓库的referenced documents 目录下,文件清单如下: - Servlet3.1规范(最终版).pdf +- Thymeleaf中⽂参考⼿册.pdf diff --git a/pictures/aop执行顺序.png b/pictures/aop执行顺序.png new file mode 100644 index 0000000000000000000000000000000000000000..0597061b590444de68c96bf0fd4f7b7b6c18b599 GIT binary patch literal 14889 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⋘6&st~%K`21EWk=1 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 vZ5wC@^DJ@Ns(ph9LRZDl(N)Wm#5Qqt+ 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 literal 0 HcmV?d00001 diff --git a/pictures/dubbo-common.png b/pictures/dubbo-common.png new file mode 100644 index 0000000000000000000000000000000000000000..992e79800c3834286541f6ddd1cc4941ab388a58 GIT binary patch literal 9107 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 S0DMq`29{Nksd#1b{=Wd#S@S~x literal 0 HcmV?d00001 diff --git a/pictures/dubbo-consumer.png b/pictures/dubbo-consumer.png new file mode 100644 index 0000000000000000000000000000000000000000..31e9ff99b3c0fc1e0bd17b31eec16df10c6c3438 GIT binary patch literal 9279 zcmaiacQ{;cxAq_=IwMAnE)ty}MD(6SlrYh|sL^{DWsFWj2+@NvqDAyx29fA3>gb~P z9-J+|^PTrP-+9mX{jslo?dN))wV$%~z3z3d9igtOL`*Vyd?#gHR}hG# zASTdLc^NIQPg^to(R8mf?(aIvqzvHic$+fG;gM0npH>9_B+|CDG8qWAC`j6xs8{qI znmzjcnQO-;cH&p;tGZ#~f{!0mJu9{zR#zySXL>kZd>i^XAUKy)XXski-bVDz(X&cs zfZ4nUKNKF?OBYWz)NpJ43dvdDv*R(f)n$l@8(}GNkqDT~ZuZV7_|dOc7qH-cM_wMg z9*Lo6VzGtGD9E?zkMEFtlWRP?M43lfjj;y$SSxJBUd~H+9UhbJ<#rjhEjbs?yY|{S zwj5w4V$;;Png6ukYhZb5pMF2*nD`IE_OvI?8S~-bavKae8jy}bt|#za-`Zc!9FfTM zzC^(`i6QR#Y9Z@wg{-HW(>7l)<@M{+T}qTrd#}^V91dcQJhJnL4v9b{lx3x3wIR4~ zF238OtdKEypYs0M8`JzHqS3Or4Tpz_o)1`pS~mI{5vA8I6Bn}XeQ7J~Dr(?8>9vSg zQ-Z|#5wP*ZbM5Bhq1rpo@ucdpe2SYk>!4kmi=f@Z#eVZYOUIo%tyI;?1=V>T#f1ka z)wiB+37==AyKbNOG6n<7UD?4sQ&TGl$V`6{)8CiT0ZdZ7OG@%<(9MI@s_M!9vfabp z7bzaH1Rw{}g~6#O*47)xL!^?RX}_J~l$xO25Mf9ck?|&f6@M0KOqu6y*B2I5>idZe*N}wv+VFJDB2&sQ0 zBxSsJzI>3jH-ni{KjO@gWaKuPV&&5@mU=wnqp$zAfWa3S+<;(A2L&nM(A-W~L-4ie7j+1#f%{WY)dy6?cTwyG{}iorW3mjg9) zAdEVC;*s2Db2e(+_GfeWDvTlsQ#*D}JipN_@%mD+Pdu*ue$efzs)>P!1FznzMZ5b_ zx5~=%4q&Cm&a+R>%knh??Til&-)e$-q&j*hIZu{_u8uRYp6V&iQ-D@|4aLI>7$>7| zZ#NPu?Sw(Sqzu}AY&G4!_G1XgnvT{?(f<-aUyxZNfyl*p8aAV$TDLK_=XBcpr7&F; z&u|!@94cMmAg%fhsEo)2$Dt7VGEHQT>=yEU+b^p8?wJNgHRI;)+PBn`KYVeyA zGHUi@btw5WJ~JOpQsodXS=-pkW#5_mzBx+id0g?}t)^c~;+q;OqZ?DJc0`;;SM}Aq zhmA5j!nX-)uDV`K+UB@0H-26|$r8@HdcrDF9|vpx#Dp@3?c}a^Ii7Mp?ZUL}NCuz| zPmfj!j(sBijl^P{$Il8F0|#B3mO97-+y=aNnF9`W(2l6}PsyK$sY~^!?Ea+jJ_Y(& z(IfZ0((HxZ%<$(KGi@&=tTh_1?o>Xb{Y-jqyiRb2=inUnLP<+r$P2sj_K)X&JzUURl77UEL%Oulp1E5q{41W4JHV?QkjS> zBx8H}wK->?I9EB0P2Qbe<7qI(vur$28RL|3wpKZxKRYcO4pb{b9{Ve|Z(9#Ohwg_2 zWwuw%nrMp7#rE!x>?*^dHu(^b^gj8o)WR=P4g_vxv2rSuA!&|XU;OOCF2Y#lUG94am8$6r1qCtuLL1O@RA z<>L>30(ah1cE^rFh>66@;OdxGdhX0hhEoKY5pd9huo1m<1Bv1U;p^fe;snBsU5VRw z2NKLs5Mkkg>ie4$6$KbW5VpXr0ybsHMR{rnP07g;{}3D=±*)LQy^XnXk1I_u0Q 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 E169$MvH$=8 literal 0 HcmV?d00001 diff --git a/pictures/dubbo-provider.png b/pictures/dubbo-provider.png new file mode 100644 index 0000000000000000000000000000000000000000..25c57eff785b53500cda230fe9490178c926ae77 GIT binary patch literal 10318 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 bv5c(~oUWZ63X$&u0$#mTl`DT?^5H)KQ2j;a literal 0 HcmV?d00001 diff --git a/pictures/spring-aop-annotation.png b/pictures/spring-aop-annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..189d0c1c263875d9a5864674492f21f8531b3e71 GIT binary patch literal 17792 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 Slf495gIJo|VjiN;Q2qmn_mubm literal 0 HcmV?d00001 diff --git a/pictures/spring+redis+ano项目目录结构.png b/pictures/spring-redis-annotation.png similarity index 100% rename from pictures/spring+redis+ano项目目录结构.png rename to pictures/spring-redis-annotation.png diff --git a/pictures/spring+redis项目目录结构.png b/pictures/spring-redis.png similarity index 100% rename from pictures/spring+redis项目目录结构.png rename to pictures/spring-redis.png diff --git a/pictures/spring-scheduling-annotation.png b/pictures/spring-scheduling-annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6b0f14fa5d29555c01685024971e0330d79cc1 GIT binary patch literal 12334 zcma)i1yoc~yY_&9beA+kcSuPiLxXg8NjC!0AuuqMpoAzON+UAJ5YjE8Al=;!A~Dqb z2fusQckg$dUx5P_O1L=OZ)GXV}yY%HLq zTN`u){KN59HT4652)pkNwAVa@v_KPQqb1egJP5=D zQiCWM1ijs#kMO45e9m!n$o`v1{kBN8rcgr9T`h9Sq?XJroxGZ!D`A~HZAI{55xe;I ztDH0Ri^6V>NOzQX%7Ll$Rq88@w-etVY>CK1ahGXM$Dyek zIcwChj?~br)w-92MC|cbs46kL2^g%9ZIb}SAj!0eaa-g?9`ol?Aes`%9UtUPh24L0un_54By+IK z#bdmhGatCLR&TUAfz>^BGcM)rd(QEzt;W|J8RoY6fqqE4$+UD+^`_F`ywR8DG;ro( zv82$y0A(I1Qh$H;`97PwsSiA-iS>KaDPDf*C6SKIu6W{Y{>hr>YU(pm9kT9g&G07y zv-7mxi~d-!H!b$(YOK}XbWAc{zrKC^P4=xj^V@s^o=i}K&iUm} zS(U4EhR(^<@+)02&-St?DfrK$JO=$gORjs<4b=BadMudLORPIAiCWQZ!o&F?Q`L4j zDfulXs?~?u`R$B@LraOY;;$=1x4UgakIEfQYOi~r_F~Il+3cI-MYKd5GXHsN8KWpQ zX|tchwHNI3fMLEF1LS?ZW;D&x92H_SIEV* zn4~PD5!L18M5DHQ(hy-=9w5%zdmv;T|I)EcTTi>oE>W&wv$Y(zf^KHn)hJbST8B!w z?Ns$>OoovVxrec=tRh{UpLZ9LQvoM^(9vxDYU}Rlsz9Pt8>7!=331Hr6WjUgTaPni zm&WnN=m1_dwa4eihwUF2??0w zjf-#7Fp1jHm;)R{*!;^659QB&=Ynl;hklOAr964f2)^h-KDb`q|I*;UQtc9}!9lo6 zE!2r4r7o>)AJalo(s}-4t1;^Vj3qC7gjmn%r3|NsFH&S zbkU%4MPwY(T!g}LgT8leLgae&k6HZ5EP;~dOxbAA1TSgB zJ;=YH;l^wgZhRxlL$CkZD!;e&;Q;*87iWtzMon%wexYIskRJKS$MM^5$!EqVD!fxWxSzBKE}!ZAZMF^lWYU71OfPtA%t32Et-=m&oc%XN?ojTw;$2 zY^Cjjv|7*leM5W=#<{yi(!2_yXY$_F8J%8;>WHv={Y-q_;K3x7TT2dMkSxAUkMF76 zU=G&>$`e=R4}+!5ae%9bOG|(AYZ%P#*SRiv%mUtcaMG?3KbDS4=&AD(QpnOy5yj-X z-(qDO@j8>L=fvXnA)M}fv4uMD=E%6+_)ze)nhmG!7~iCli1#6*juSHMKt_joWAya; zapmAHZ-AUkvOaCrJ(cmHtQud@Gxxlns@p}%;HGp8=SQ}?DeF_?5!lvQto!8}`ww=F z#fsN?jH&j0a1P9maXo{M*!CYbqTQ%Oh?4Zd5$LHc#@*`Bhy81!o&yj2Vu z6z&BAYykiICf@twXpFwpL3bIIa9s98!BynXV-q@o0#t`ZvV92Q@@@&9 zK4toh)8_4$HlfrGnv9*j6Ya;yu8>a}RUkp3``wLMAK!=gs2ouz{uQ?Ue1Uf@ zAe)5eS5#K;mRCbk4`cG1tHM}X;k(yhjjTi zH|v_jms)o}^*-7>__l2d(!k$TY*Q( z;*FYzy$toOJ2EwpJX)$h?C#$^eK9eW=Bj&!()4+&bNFQmz{#$d%dpp2`Pw{j6(oLp zUow3N-}1|_vka7AS2g&ME#%8GUl&izXjSko%7tHuf{MhG)cN{8+zVV8zTS07(gIx^ z&Dl%&`eXHp3v|qc9v-8ofn~FQ>c&J=S>|1fsMx$Nt<6|6D6mWYbAFZeY=9ru&94fQ!F;J zZS1|d(Ak>87>ar2>H&cnr$7Dm#R<31E&2VAfTCl^ql=tE4}yX7!<%Fmq{X;jcnVz* z=G7@x@uKCum6uO{jplRJ617Vx6P4n83*zVL(Qgiyxq1uxBz5p((clqc9ejOrru`Z8 z%QJwlD@(5OHe8r?d|#VjF6FBDVR2v6nf>!tkLM@uigpunpLYYcuI53_5|-h#O%fc% zM-mhA3_4l+rb6Z?D8>)2DfJS!8BK@nbsu(uUk{e-A1A!25^Om8S#y`mE2d%)84=Ro zilqb|zYm;gK*^ur3~7fn0JI>od4=NSr@_6jx##nv@#X5oenswc1-CxVBdF2z8*yY1 z4Cksas#E}91UCP{u#f18(DTU65=;6=N4RH1)SdyNFW>x_U^)qm+l&n4?K_TXGp!!l z6uZf_cv2VP<#vlJi8-XbTPB|T)a- z;?$??=UwVi;b;n`Up z*U2+qp+6AGmwM!!iRelRU0x<{v6BikbPJN=m!p%?$lDr1xCIe?Znu9((yd z$k?m0Y%Qa%!07Lj$KPYVlHb0LQrJf*Q*<)E7`!Ltcj%Dmh+P6O4&!Vfk|Kd3&FMhca1)w{n^0?Ly{f~ zeAz(K`Dq{T07xM+M#khGr7mlsvRSnsiT7`6FzHWV_J9^}iH~Nq#}GJC_;EUs&?BsT zBWfYmdufUjv7~;nr@wbM7ANrpT|Ii;XPCf!-oT{;;6zZQ2>4!mb)mc(=1XkVH07^j zj}xXji68J9RMC%341BKOFocOc>=g?(nTh)rMVDa{CB|Eb4LSl#(#7HF4E$(^Ip-U( zcK}nsp4N{RiMJd?{c9lZKI!`Gk9s)$yw&^r@<0r7ccAYZLEu<3NAg5*Co=jQT7}4; zFNZqL&d%)I-795wLJi%7V`{|{E6)ntJVg>jB+co_NfOo?7%B&K`zb)zVNfu7eZXot z$7nwT@33^=rj1+orcFYr8J-vr^a&eN%;@04fWCi;eZhaXApSP4eCxNG8U8h#lYTD7 zx7(g+2&?dV(LNpnqVYt)5cHeV(!5o9-q_nd?;PA zA_l<-Q~-ZXIYTw13Eql!Osu=>11+Hc#;lr-5%`g;>{w8O0B!iX9T;h_!c@%vR}9aN zrJmFCBA@d=oZhMCP9sSV75sr|_09sn^*UhZ#mX}+a!*$$!d+rfY_iH2x?IVGE){bf zmni5?XCpS<)15IF&3BR>P1ii=$WN|=-~UZp-QKgW)7e(0UnJX=Ov4AR z0(++QbBZEhY(~wLJnjWu^csxWZ6+(=tx(gdaBsn<5~?iLa&$8H7$|RH(8<@-<&y=i zi{?NwPpfk{P2DS!bo6ZK({WPa#OUMdf!|?lm>8OB{K?-UjpT(WAYdj1n(gmdg$fS8 zinHx#UTWIPc-hG}y=P@%C1}qWKPzz*<=;8q zVO!N=&kEb{6oN?hM~l${pZ`k0ao}z8?LDpgU@lO`l*$w(0`_cC*-~aD&@>T`w)rl& z-N04HjVDEer}(&6^|1iHsbcd2=jHF&QnlPtO3i8l_Cn~&pGI*$)O?Ut5M=OdKN(zc zF0CcALt|h$HJsYYIo6p5M`Mk)tRz*?>cilX_wo`rXgObqGb{}|o;o}-xD?D&XY7Ub zg&W_*-ST6MlHhNI6bakGEpBfZMyc1Cz+1g%W=>aCXN@E2CZITA|Gb&v4=$SIswk@dz>{=4 zh(UUKz08?Ve}8L(7;QX`f?(z@Xe-^MRAle-q|v1dF7;2ylH1Nxe?%jy;oVgI!UKXCsqY@ywcnJ$w$@M#c;ujgSJmEkijz! zmAO+hf-+$LP1yLixW7zAK#5)Pd7;YO@17@xWS9}c7m6I)#%nu1*QL8rzRLthIpMyN zXEs#T0bGUIz;KP^L>F?ZdUIpGQJIRdT$*_gU2$M1_`HzuRQK^+lZQTlS!{K&Pp|hbyb>a;ixSj&I-kwAWylEHxEE3ZY0^hqe2}*k#i!;GY`IJP7l7ZF9 zUMU9CZh>6aVOhZ!5OZAZd8Jhcd%b*hY3+d)v9mk+vaH4bpCZq{9}B-~5vR{qK}7LR z3mt2-hi?|FBYv(=)$XZ>`u98XB_@?3reca7J-G4kN zId2x`2?gFCb?mqos{mAyn0A_L{r;)t-Se8J<_N!bhiHH+YXZrmH}S>iEeXJKt5QM;EA>A+d+Y&=EM?)={SgTqYJyqFRkY4`1`^p=Pgt5xOq zx@Mv!wERb{7C%Z3K9q~?r?dr0?MA=8JY;tqep1&ERJ4v1u$$_=4&j$w9M9i1BJvmP z&{J&ou_N7;3n7xMGUxW>XrvAXzf;}r!cmf$gV~t}eO52QqBx5GO?4`r%{2ciql}@}A`V{=}9&tK5dQrdITrJX)?2 zs2*RTi==U(okx>=-544K$M0z;?SE%o30`e9Hi|zr9~ww)uxf2mi8k10k(pU{A&SFm z8ERB<*+>TG9-2~}hwhijAjqQ=n>6?f9V~(n(Y^2d@p%2UMuIV|266l^Ivq*e7 zhTrk2XMd8;q!H@Svz)N@Yur99rjJNTam!lSZks1~9!P!Fb|v5A!Q0QQ8ifOi=i@&F zSneN&?I22BFPfbG&K1aeWeHz61LV)boCB7N;%5=@H;@@mR6s2K0M|5DnxZ3r6hITy zv6vAIA)h?Zj?R^$)|jv|#c3s2E3OSY(ytpG^a6b5yHB z$v9x?VMN`R6)_`HG#n&M*^Ati%~K{|1Gnp8DWw4h2t!{7-!hj;nTdiDT$DO|c|}a` z-NmOgW{D9K$M6bowy6b*!OGgK>(JK)b^37B$fg<>08(TZSQeO3riayr@wZd-R`)qU z4K1y;SVikFOSAT&cQ|PGeC0dBH2C^dsQzT6+UI@jIlk^h zEQ9(I>n4+NDguzrXbqveDZ)gD^-*`Ir^6*h_pIYlGBzE!;L%i#s}R5sOB?d0*3`#Z zfwbdS<2Y_t*|s74+Zgdaz}kfg}-iQ|u;TYU?M zm3K4nju$a25zRJSSR3)sj~a{RP!cd^_Xh97Fuyb7L}8@;BNZg#VZ50cpK*>s4>ynk z02_Ll$WZ5XEO!!Mqz+@@=3=suB;2)&x@|y5q*zlXlB%>9&UaRK3#L`RkE1|P0C(`I zP@s5RD;gvU%YK1%jN$F+d0+6BZ*BIEbr!u=i`s$FxLiAu9RVzvj{fp<`^den}sHS%iC)eP{?Y-Y!%rl{lM;&`(N2ncL}GO3@0ME4VrhYi>> z6vT4*)M^wJ6~8_G^37o*z$IdT+;|z_z~#2Ek{buNY^A_Dj~zHnhKJ5^ZCB=x$;`U0z80f zMJ7LAByY&YFlBhR|ijg)<^$ z`68+#=#Ec;@`qHIOZK(=30X)r;c)3%dC2bh=B{d$tF8PEyYa+gJSW)OO}r*p_+2bR zB@g}(G(2V?S=FgrB;ji(wXvRj!4EA#@clcI)47vtF)k6@9J^z-#JhteRM3)^S+-f;X|vZ8s2 zTn$FVkVj)vmNQmgshwc-0h|UPSwb!0sCTAx3s?8pP+QO@)ej-Et5wAL|~F zX%fAh>4DQfTAvY`A4Cw}-nVD#A9u}7G|_oUmx7Z?vyx1fVS<_t`QuB@VE)p)6i#jZEzDE6_kh`1LC~G$I4!p1dLVj z#!}DmP?$!&i|PHkN;6&waN$`eGkW(DOG=0$WIs~IBr4^f3LIZ2L#54M0dCA?b{!Dl{K!5q7d{30yUQ(8b?J&f zIG9-ncBG42smIiih{>7MA;GY=FaVpyiX9uNL+d^RN^9N}loAVAR zQVJaTG&tsEeyy#nifaRYGrnM4@G(-JK&?sy%P(ZrHmfe*%$~(eLIP`+6_JF%(vNds zy{j3QGKqyMSAVX7+U~!DGBIf}y%8n9$hZ^PUWyuBpPV!AJhO+SbXoVr5U>f6*Bg7e zL-4T4+{qkKhx3_-O{hQeNP?ETB+mI$mmiSeeD-Us)I-J{o-Pv8+>V)if(s3gpm#Dy zv-_g9(FXEst}U^PS*S%UW(Sz}^%kox^6Rux;bY~}Q0%X8nfxVOLt`yW%!)(>W!}sR z0kJ~N7cx`q<)82G0@Yva5TC-x0!}e`ca(4s>iR!&!Zjjm%mnFVFrXx!g?D zr~GYn=#afX0FH&Q(u7oF@#?8Ul4}9AD8Q9RFZ*u_uvTb3$SI^5#v(zm^!@o)ZB;7; z3N4lHWBni6s>s!dm9nZYOF9;5)Fm!?vHL7jA+lZQe+sFyYf#{;O(88itfQyoocJbn z3Xqdnds1GTCpAq0`>wXWi1!p|Ne!n~_a2T|1ph7gFCj;%zJMRjUby{wYBjx@vY?iTd_l{3OH!0j0W z-GE_AEe8~VV*^Z@)1c)Dn>*dwIfWj~1a=MlD_{Q;L%$V@FNU;?3lWq2)cChbceR6N z%=G{arSp5?lE|Z*!zjFXN9eX(G zTNb!s%j?#<@LELD0U*dYK zq0$)FTUSAQD(zYI^9JK$kTDC*>iwNOuNB*CQQ2obD%F2}8%`ldu>8FI=jShkZ%Mjn zy8uNyO$I^| z1R5|v1=r2mO{*wTR)Mg4yVD_TZ>Ru*4HUIrz9j$QV?aN0UNf+fyu|*u6E4^x83%X+ z(Q|im=$dlHKAA6l$_-i?<&iwvn>GctYZ+U|#mhFLw*~Ek&swj=_?uDrCN*34rk9~fuYNmpWQSIoDFGOubvH#g#|b779p)_$y-Ns`X0I-~tfq}s)b zJ*QX3@dYcRoiD!ZYMn1R}Q04d{7tCgH4si za_8$`y}yxU9XFMQLeqvR^WGXUI+?D+>h0HA7O)dw6v&(mULhU6`fO7m&#iy;I(ju$ z9p&Xgy@V>A$TfT3mxy0n5udUPg72mM^M*_Vcev z0N?VzT;=jto=Za~i{0P+#Xy3P10auTumw*(%&vV(f85J`zBIW9JvP@?-0Il_nl8Md zODs_(2wt2$>E6KRI7Y~-Vb23K3dJm2 zLMb8NW1t1JvzA5suU^ACIFJS6Z1H37G~PkI7A6mpTOt)x_tRiC$gM(XbWP zZ30fusQ@*8c(7w@{pEbZ1L=?e%DWJ`J3vPOZ9ATVc`X%J2y`umx;pCe{6~?wb|?fy z`ARm!UR&tx2e!i-!_AuXbAWkRYzXmz3padzPy<*vD)AJkF2A|_?|OT;&`<}Z)Ek+U z>{ zPf!w(AOwKUdk2`s(jx13d@)@~_ZAMK+jyYe@)WC?Rr_0Klx+6e)HlJ&{O@Gp^(A#I zzr?EGL3X;feUXN3InWJP1@5=tP6>JJ}U!&3RlQxJ6jmraVbVmmk<4Y%#qf8jD^AsS&N)tpT1bZ`ppH1X<+>H~Y z*+Z5ABwN%+vne4r=b=Rk40djWHU#0T8BH%KsefMALaV{Cfie zwaerQ76^+ueqb(WB)DZdoo?^WQu@};Y4@(TTMNkX05}oKo?(Zd?>z)X+Q$_K$&=TRK>=OiBl#-*4S6)D-xm!+(^uPK2UdJF)M^;R z)^I9|kENw{%=9MIBZAWqPh##vBtIjg44myAPi78b8R-LF2VYVz63xhIO) z#3f?EJ^5f(ETqks(9eRyG-WuZfBJ#Pxk}G%CZIj0Qkd{+u8jR+B;aS|N?AUmPgs%> zWBkDe6Yopxlrm>Qe}Am|j3F2UUNe!~S=OD&`K@>yd0|+&ZKt5SZxV~xMFR=mm^+Ez zWry_D;A+}B&%S5kl^uPuVaEM6lMjb%hbfHfn7F}(dMS+lKk7~f3ag-f}_Lse~4H~J)Ga0 zCnXWJ93|V^(r@bo4%ai!1n8S5Cefm22G(yLMQ1%tc~yDB=+zv93RW~3Tkayf5(zS7ioz-P*Fy*rAHy7bR6+Rzwo zV`tR{yGj*fcc{xpAtyLW}E%7|~E!amR{3OYe+^x!8nzGNRMy~0kFyESkXn+`zx2{zMIOYES z{!F<)?+n{%q1V;imzzMsC^CNfS`k|l@>1&$OO*r3scRSRs%-<)KU}VO>Y6P;!A%e% zp;pK$tUAO3eI)6p#=|-z_k<9*#$ulIVAAG>{)SK0dL@k;DoGdh74!I6{oM&bFiy)& zFhKm0VgN%*MC8Tvv}wbt+w6<46uUtI!}FTwOCBmHkb z?qa~0CNC_ENTE{JlEH4}MTTbOP24l1<@Q8z>p=%9;U+Eq6m=gWM{;SSb%CC#7XtXhrB; z`>-1qVv$+>Ia-cq97KWIGqhzBT2gPd=c?CYUW*4j|79w|Rhwft+-jD1@4G0a8ipWE zO=G2}JetBRdK?9=5T*4&7LOxKDwFNy2Sa4DI$JF1zCB!S!q+2nQ4S`Qt}lw%dY|V| zv8f_WF~(kASKeA~BvQ?NPv6oZIkOqc zlPNy;H1~OcE^d{BD(j|Th%fv|tcl?okzVki2Y1sY7IZ8 zfw9fh_S+?iXp0nWy*DHZSUmY$cy)E9CC3IhBI-3|XZbZBo%55j=TUXQ_)Uyd?TbAl zC$6lIwC!*8gA%;r;W$vSCWkh_LUNd&RqDHa?rYFtfMCo|S#2|9&%-B1*kM8=(ssd` z1FOd%`7Rg(<+&BwQl7bNVu&Zw8A)Jiiyso2_EG-!la2Z?!yjYV8FG%4^%;(yI$d=+ z-|nHJe>*`vIT|P^MnUmVhcBHPM^zQ@hf?A_X86wK8YL)22O9$L^AvE9irB@tsmg}* z_K$WX5aekE#fAcf!%S(li=Dtotl%j4YCyNVu=I6S_(A;LugM>$)9TqW>#0*%n^nsg zMG$z1Em@EvaBSJ^_wr)K$HTi|&~K&^RCoF@Z?NiL=MGp`|NA=n*KJ(?dL@c+?gSJ4 V;RQ(>u-6}?rt}0-_1Gr*{{a+tK#%|c literal 0 HcmV?d00001 diff --git a/pictures/spring-scheduling.png b/pictures/spring-scheduling.png new file mode 100644 index 0000000000000000000000000000000000000000..18ff1d7c96be6c16f324b680867a26533946f9db GIT binary patch literal 14333 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 FCIBHI@&f<> literal 0 HcmV?d00001 diff --git a/spring/spring-aop-annotation/README.md b/spring/spring-aop-annotation/README.md new file mode 100644 index 0000000..43778a6 --- /dev/null +++ b/spring/spring-aop-annotation/README.md @@ -0,0 +1,169 @@ +# spring AOP(注解方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 切面配置位于com.heibaiying.config下AopConfig.java文件; +2. 自定义切面位于advice下,其中CustomAdvice是标准的自定义切面,FirstAdvice和SecondAdvice用于测试多切面共同作用于同一个被切入点时的执行顺序; +3. OrderService是待切入方法。 + +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-aop-annotation.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入aop依赖包 + +```xml + + + org.springframework + spring-aop + ${spring-base-version} + +``` + + + +## 二、spring aop + +#### 2.1 创建待切入接口及其实现类 + +```java +public interface OrderService { + + Order queryOrder(Long id); + + Order createOrder(Long id, String productName); +} +``` + +```java +public class OrderServiceImpl implements OrderService { + + public Order queryOrder(Long id) { + return new Order(id, "product", new Date()); + } + + public Order createOrder(Long id, String productName) { + // 模拟抛出异常 + // int j = 1 / 0; + return new Order(id, "new Product", new Date()); + } +} + +``` + +#### 2.2 创建自定义切面类 + +注:@Pointcut的值可以是多个切面表达式的组合。 + +```java +/** + * @author : heibaiying + * @description : 自定义切面 + */ +@Aspect +@Component //除了加上@Aspect外 还需要声明为spring的组件 @Aspect只是一个切面声明 +public class CustomAdvice { + + + /** + * 使用 || , or 表示或 + * 使用 && , and 表示与 + * ! 表示非 + */ + @Pointcut("execution(* com.heibaiying.service.OrderService.*(..)) && !execution(* com.heibaiying.service.OrderService.deleteOrder(..))") + private void pointCut() { + + } + + @Before("pointCut()") + public void before(JoinPoint joinPoint) { + //获取节点名称 + String name = joinPoint.getSignature().getName(); + Object[] args = joinPoint.getArgs(); + System.out.println(name + "方法调用前:获取调用参数" + Arrays.toString(args)); + } + + // returning 参数用于指定返回结果与哪一个参数绑定 + @AfterReturning(pointcut = "pointCut()", returning = "result") + public void afterReturning(JoinPoint joinPoint, Object result) { + System.out.println("后置返回通知结果" + result); + } + + @Around("pointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + System.out.println("环绕通知-前"); + //调用目标方法 + Object proceed = joinPoint.proceed(); + System.out.println("环绕通知-后"); + return proceed; + } + + // throwing 参数用于指定抛出的异常与哪一个参数绑定 + @AfterThrowing(pointcut = "pointCut()", throwing = "exception") + public void afterThrowing(JoinPoint joinPoint, Exception exception) { + System.err.println("后置异常通知:" + exception); + } + + + @After("pointCut()") + public void after(JoinPoint joinPoint) { + System.out.println("后置通知"); + } +} + +``` + +#### 2.3 配置切面 + +```java +/** + * @author : heibaiying + * @description : 开启切面配置 + */ +@Configuration +@ComponentScan("com.heibaiying.*") +@EnableAspectJAutoProxy // 开启@Aspect注解支持 等价于 +public class AopConfig { +} +``` + +#### 2.4 测试切面 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = AopConfig.class) +public class AopTest { + + + @Autowired + private OrderService orderService; + + @Test + public void saveAndQuery() { + orderService.createOrder(1283929319L, "手机"); + orderService.queryOrder(4891894129L); + } + + /** + * 多个切面作用于同一个切入点时,可以用@Order指定切面的执行顺序 + * 优先级高的切面在切入方法前执行的通知(before)会优先执行,但是位于方法后执行的通知(after,afterReturning)反而会延后执行 + */ + @Test + public void delete() { + orderService.deleteOrder(12793179L); + } +} +``` + +#### 2.5 切面执行顺序 + +- 多个切面作用于同一个切入点时,可以用@Order指定切面的执行顺序 + +- 优先级高的切面在切入方法前执行的通知(before)会优先执行,但是位于方法后执行的通知(after,afterReturning)反而会延后执行,类似于同心圆原理。 + + ![aop执行顺序](D:\spring-samples-for-all\pictures\aop执行顺序.png) \ No newline at end of file diff --git a/spring/spring-aop-annotation/src/main/java/com/heibaiying/advice/CustomAdvice.java b/spring/spring-aop-annotation/src/main/java/com/heibaiying/advice/CustomAdvice.java index eaa002e..68e323d 100644 --- a/spring/spring-aop-annotation/src/main/java/com/heibaiying/advice/CustomAdvice.java +++ b/spring/spring-aop-annotation/src/main/java/com/heibaiying/advice/CustomAdvice.java @@ -34,6 +34,7 @@ public class CustomAdvice { System.out.println(name + "方法调用前:获取调用参数" + Arrays.toString(args)); } + // returning 参数用于指定返回结果与哪一个参数绑定 @AfterReturning(pointcut = "pointCut()", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result) { System.out.println("后置返回通知结果" + result); @@ -48,6 +49,7 @@ public class CustomAdvice { return proceed; } + // throwing 参数用于指定抛出的异常与哪一个参数绑定 @AfterThrowing(pointcut = "pointCut()", throwing = "exception") public void afterThrowing(JoinPoint joinPoint, Exception exception) { System.err.println("后置异常通知:" + exception); diff --git a/spring/spring-aop-annotation/src/test/java/com/heibaiying/aop/AopTest.java b/spring/spring-aop-annotation/src/test/java/com/heibaiying/aop/AopTest.java index 0af02e2..16cd204 100644 --- a/spring/spring-aop-annotation/src/test/java/com/heibaiying/aop/AopTest.java +++ b/spring/spring-aop-annotation/src/test/java/com/heibaiying/aop/AopTest.java @@ -5,13 +5,11 @@ import com.heibaiying.service.OrderService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; /** * @author : heibaiying - * @description : 关于多个切面在同一个切入点上执行顺序的例子 可以在spring-aop-annotation 中查看 */ @RunWith(SpringRunner.class) diff --git a/spring/spring-aop/README.md b/spring/spring-aop/README.md new file mode 100644 index 0000000..3680b9c --- /dev/null +++ b/spring/spring-aop/README.md @@ -0,0 +1,162 @@ +# spring AOP(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +切面配置位于resources下的aop.xml文件,其中CustomAdvice是自定义切面类,OrderService是待切入的方法。 + +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-aop.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入aop依赖包 + +```xml + + + org.springframework + spring-aop + ${spring-base-version} + +``` + + + +## 二、spring aop + +#### 2.1 创建待切入接口及其实现类 + +```java +public interface OrderService { + + Order queryOrder(Long id); + + Order createOrder(Long id, String productName); +} +``` + +```java +public class OrderServiceImpl implements OrderService { + + public Order queryOrder(Long id) { + return new Order(id, "product", new Date()); + } + + public Order createOrder(Long id, String productName) { + // 模拟抛出异常 + // int j = 1 / 0; + return new Order(id, "new Product", new Date()); + } +} + +``` + +#### 2.2 创建自定义切面类 + +```java +/** + * @author : heibaiying + * @description : 自定义切面 + */ +public class CustomAdvice { + + + //前置通知 + public void before(JoinPoint joinPoint) { + //获取节点名称 + String name = joinPoint.getSignature().getName(); + Object[] args = joinPoint.getArgs(); + System.out.println(name + "方法调用前:获取调用参数" + Arrays.toString(args)); + } + + //后置通知(抛出异常后不会被执行) + public void afterReturning(JoinPoint joinPoint, Object result) { + System.out.println("后置返回通知结果" + result); + } + + //环绕通知 + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + System.out.println("环绕通知-前"); + //调用目标方法 + Object proceed = joinPoint.proceed(); + System.out.println("环绕通知-后"); + return proceed; + } + + //异常通知 + public void afterException(JoinPoint joinPoint, Exception exception) { + System.err.println("后置异常通知:" + exception); + } + + ; + + // 后置通知 总会执行 但是不能访问到返回值 + public void after(JoinPoint joinPoint) { + System.out.println("后置通知"); + } +} + +``` + +#### 2.3 配置切面 + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.4 测试切面 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration("classpath:aop.xml") +public class AopTest { + + @Autowired + private OrderService orderService; + + @Test + public void save() { + orderService.createOrder(1283929319L, "手机"); + orderService.queryOrder(4891894129L); + } +} +``` + + diff --git a/spring/spring-dubbo-annotation/README.md b/spring/spring-dubbo-annotation/README.md new file mode 100644 index 0000000..bf9d8fb --- /dev/null +++ b/spring/spring-dubbo-annotation/README.md @@ -0,0 +1,327 @@ +# spring 整合 dubbo(注解方式) + +## 一、 项目结构说明 + +1.1 按照dubbo 文档推荐的服务最佳实践,建议将服务接口、服务模型、服务异常等均放在 API 包中,所以项目采用maven多模块的构建方式,在spring-dubbo-annotation下构建三个子模块: + +1. dubbo-ano-common 是公共模块,用于存放公共的接口和bean,被dubbo-ano-provider和dubbo-ano-provider在pom.xml中引用; +2. dubbo-ano-provider 是服务的提供者,提供商品的查询服务; +3. dubbo-ano-provider 是服务的消费者,调用provider提供的查询服务。 + +1.2 本项目dubbo的搭建采用zookeeper作为注册中心, 关于zookeeper的安装和基本操作可以参见我的手记[Zookeeper 基础命令与Java客户端](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/ZooKeeper/ZooKeeper%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%E4%B8%8EJava%E5%AE%A2%E6%88%B7%E7%AB%AF.md) + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-dubbo.png) + + + +## 二、项目依赖 + +**在父工程的项目中同一导入依赖dubbo依赖的的jar包** + +这里需要注意的是ZooKeeper 3.5.x 和 ZooKeeper 3.4.x 是存在不兼容的情况 详见官网解释[ZooKeeper Version Compatibility](https://curator.apache.org/zk-compatibility.html), zookeeper 3.5 目前是beta版本,所以zookeeper 我选择的版本是 zookeeper-3.4.9 作为服务端。但默认情况下 curator-framework自动引用的最新的3.5的版本客户端,会出现 KeeperException$UnimplementedException 异常 + +```xml + +com.alibaba +dubbo +2.6.2 + + + org.apache.curator + curator-framework + 4.0.0 + + + org.apache.zookeeper + zookeeper + + + + + org.apache.zookeeper + zookeeper + 3.4.13 + +``` + + + +## 三、公共模块(dubbo-ano-common) + +- api 下为公共的调用接口; +- bean 下为公共的实体类。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-ano-common.png) + +## 四、 服务提供者(dubbo-ano-provider) + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-ano-provider.png) + +#### 4.1 提供方配置 + +```java +@Configuration +public class DubboConfiguration { + + /** + * 提供方应用信息,用于计算依赖关系 + */ + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(); + applicationConfig.setName("dubbo-ano-provider"); + return applicationConfig; + } + + /** + * 使用zookeeper注册中心暴露服务地址 + */ + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://127.0.0.1:2181"); + registryConfig.setClient("curator"); + return registryConfig; + } + + /** + * 用dubbo协议在20880端口暴露服务 + */ + @Bean + public ProtocolConfig protocolConfig() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setName("dubbo"); + protocolConfig.setPort(20880); + return protocolConfig; + } +} +``` + +#### 4.2 使用注解@Service暴露服务 + +需要注意的是这里的@Service注解不是spring的注解,而是dubbo的注解 com.alibaba.dubbo.config.annotation.Service + +```java +package com.heibaiying.service; + +import com.alibaba.dubbo.config.annotation.Service; +import com.heibaiying.api.IProductService; +import com.heibaiying.bean.Product; + + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author : heibaiying + * @description : 产品提供接口实现类 + */ +@Service(timeout = 5000) +public class ProductService implements IProductService { + + private static List productList = new ArrayList<>(); + + static { + for (int i = 0; i < 20; i++) { + productList.add(new Product(i, "产品" + i, i / 2 == 0, new Date(), 66.66f * i)); + } + } + + public Product queryProductById(int id) { + for (Product product : productList) { + if (product.getId() == id) { + return product; + } + } + return null; + } + + public List queryAllProducts() { + return productList; + } +} +``` + +#### + +## 五、服务消费者(dubbo-ano-consumer) + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-ano-consumer.png) + +#### 1.消费方的配置 + +```java +@Configuration +public class DubboConfiguration { + + /** + * 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 + */ + @Bean + public ApplicationConfig applicationConfig() { + ApplicationConfig applicationConfig = new ApplicationConfig(); + applicationConfig.setName("dubbo-ano-consumer"); + return applicationConfig; + } + + /** + * 设置调用服务超时时间 + * 关闭所有服务的启动时检查 + */ + @Bean + public ConsumerConfig consumerConfig() { + ConsumerConfig consumerConfig = new ConsumerConfig(); + consumerConfig.setTimeout(3000); + consumerConfig.setCheck(false); + return consumerConfig; + } + + /** + * 使用zookeeper注册中心暴露发现服务地址 + */ + @Bean + public RegistryConfig registryConfig() { + RegistryConfig registryConfig = new RegistryConfig(); + registryConfig.setAddress("zookeeper://127.0.0.1:2181"); + registryConfig.setClient("curator"); + return registryConfig; + } + +} +``` + +#### 2.使用注解@Reference引用远程服务 + +```java +package com.heibaiying.controller; + +import com.alibaba.dubbo.config.annotation.Reference; +import com.heibaiying.api.IProductService; +import com.heibaiying.bean.Product; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.List; + +@Controller +@RequestMapping("sell") +public class SellController { + + // dubbo远程引用注解 + @Reference + private IProductService productService; + + @RequestMapping + public String productList(Model model) { + List products = productService.queryAllProducts(); + model.addAttribute("products", products); + return "products"; + } + + @RequestMapping("product/{id}") + public String productDetail(@PathVariable int id, Model model) { + Product product = productService.queryProductById(id); + model.addAttribute("product", product); + return "product"; + } +} + +``` + +## 六、项目构建的说明 + +因为在项目中,consumer和provider模块均依赖公共模块,所以在构建consumer和provider项目前需要将common 模块安装到本地仓库,**依次**对**父工程**和**common模块**执行: + +```shell +mvn install -Dmaven.test.skip = true +``` + +consumer中 pom.xml如下 + +```xml + + + + spring-dubbo-annotation + com.heibaiying + 1.0-SNAPSHOT + + 4.0.0 + + dubbo-ano-consumer + + + + com.heibaiying + dubbo-ano-common + 1.0-SNAPSHOT + compile + + + + +``` + +provider中 pom.xml如下 + +```xml + + + + spring-dubbo-annotation + com.heibaiying + 1.0-SNAPSHOT + + 4.0.0 + + dubbo-ano-provider + + + + com.heibaiying + dubbo-ano-common + 1.0-SNAPSHOT + compile + + + + +``` + +## 七、关于dubbo新版本管理控制台的安装说明 + +安装: + +```sh +git clone https://github.com/apache/incubator-dubbo-ops.git /var/tmp/dubbo-ops +cd /var/tmp/dubbo-ops +mvn clean package +``` + +配置: + +```sh +配置文件为: +dubbo-admin-backend/src/main/resources/application.properties +主要的配置有 默认的配置就是127.0.0.1:2181: +dubbo.registry.address=zookeeper://127.0.0.1:2181 +``` + +启动: + +```sh +mvn --projects dubbo-admin-backend spring-boot:run +``` + +访问: + +``` +http://127.0.0.1:8080 +``` \ No newline at end of file diff --git a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/DispatcherServletInitializer.java b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/DispatcherServletInitializer.java index 229e828..8323bf4 100644 --- a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/DispatcherServletInitializer.java +++ b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/DispatcherServletInitializer.java @@ -4,7 +4,7 @@ import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatche /** * @author : heibaiying - * @description : 前端过滤器配置 + * @description : 前端控制器配置 */ public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { diff --git a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java index 4185405..59f3533 100644 --- a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java +++ b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java @@ -14,6 +14,9 @@ import org.springframework.context.annotation.Configuration; @Configuration public class DubboConfiguration { + /** + * 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 + */ @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); @@ -21,6 +24,10 @@ public class DubboConfiguration { return applicationConfig; } + /** + * 设置调用服务超时时间 + * 关闭所有服务的启动时检查 + */ @Bean public ConsumerConfig consumerConfig() { ConsumerConfig consumerConfig = new ConsumerConfig(); @@ -29,6 +36,9 @@ public class DubboConfiguration { return consumerConfig; } + /** + * 使用zookeeper注册中心暴露发现服务地址 + */ @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); @@ -37,11 +47,4 @@ public class DubboConfiguration { return registryConfig; } - @Bean - public ProtocolConfig protocolConfig() { - ProtocolConfig protocolConfig = new ProtocolConfig(); - protocolConfig.setName("dubbo"); - protocolConfig.setPort(20880); - return protocolConfig; - } } diff --git a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/controller/SellController.java b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/controller/SellController.java index 2444fa0..6f70b95 100644 --- a/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/controller/SellController.java +++ b/spring/spring-dubbo-annotation/dubbo-ano-consumer/src/main/java/com/heibaiying/controller/SellController.java @@ -12,7 +12,7 @@ import java.util.List; /** * @author : heibaiying - * @description : + * @description :消费服务 */ @Controller @RequestMapping("sell") diff --git a/spring/spring-dubbo-annotation/dubbo-ano-provider/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java b/spring/spring-dubbo-annotation/dubbo-ano-provider/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java index 1d295f7..3c478e4 100644 --- a/spring/spring-dubbo-annotation/dubbo-ano-provider/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java +++ b/spring/spring-dubbo-annotation/dubbo-ano-provider/src/main/java/com/heibaiying/config/dubbo/DubboConfiguration.java @@ -1,6 +1,7 @@ package com.heibaiying.config.dubbo; import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.RegistryConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,6 +13,9 @@ import org.springframework.context.annotation.Configuration; @Configuration public class DubboConfiguration { + /** + * 提供方应用信息,用于计算依赖关系 + */ @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); @@ -19,6 +23,9 @@ public class DubboConfiguration { return applicationConfig; } + /** + * 使用zookeeper注册中心暴露服务地址 + */ @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); @@ -26,4 +33,15 @@ public class DubboConfiguration { registryConfig.setClient("curator"); return registryConfig; } + + /** + * 用dubbo协议在20880端口暴露服务 + */ + @Bean + public ProtocolConfig protocolConfig() { + ProtocolConfig protocolConfig = new ProtocolConfig(); + protocolConfig.setName("dubbo"); + protocolConfig.setPort(20880); + return protocolConfig; + } } diff --git a/spring/spring-dubbo/README.md b/spring/spring-dubbo/README.md new file mode 100644 index 0000000..52b799b --- /dev/null +++ b/spring/spring-dubbo/README.md @@ -0,0 +1,279 @@ +# spring 整合 dubbo(xml配置方式) + +## 一、 项目结构说明 + +1.1 按照dubbo 文档推荐的服务最佳实践,建议将服务接口、服务模型、服务异常等均放在 API 包中,所以项目采用maven多模块的构建方式,在spring-dubbo下构建三个子模块: + +1. dubbo-common 是公共模块,用于存放公共的接口和bean,被dubbo-provider和dubbo-provider在pom.xml中引用; +2. dubbo-provider 是服务的提供者,提供商品的查询服务; +3. dubbo-provider 是服务的消费者,调用provider提供的查询服务。 + +1.2 本项目dubbo的搭建采用zookeeper作为注册中心, 关于zookeeper的安装和基本操作可以参见我的手记[Zookeeper 基础命令与Java客户端](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/ZooKeeper/ZooKeeper%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA%E4%B8%8EJava%E5%AE%A2%E6%88%B7%E7%AB%AF.md) + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-dubbo.png) + + + +## 二、项目依赖 + +**在父工程的项目中同一导入依赖dubbo依赖的的jar包** + +这里需要注意的是ZooKeeper 3.5.x 和 ZooKeeper 3.4.x 是存在不兼容的情况 详见官网解释[ZooKeeper Version Compatibility](https://curator.apache.org/zk-compatibility.html), zookeeper 3.5 目前是beta版本,所以zookeeper 我选择的版本是 zookeeper-3.4.9 作为服务端。但默认情况下 curator-framework自动引用的最新的3.5的版本客户端,会出现 KeeperException$UnimplementedException 异常 + +```xml + +com.alibaba +dubbo +2.6.2 + + + org.apache.curator + curator-framework + 4.0.0 + + + org.apache.zookeeper + zookeeper + + + + + org.apache.zookeeper + zookeeper + 3.4.13 + +``` + + + +## 三、公共模块(dubbo-common) + +- api 下为公共的调用接口; +- bean 下为公共的实体类。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-common.png) + +## 四、 服务提供者(dubbo-provider) + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-provider.png) + +#### 4.1 productService是服务的提供者( 商品数据用模拟数据展示) + +注:这里实现的接口IProductService来源于公共模块 + +```java +/** + * @author : heibaiying + * @description : 产品提供接口实现类 + */ +@Service +public class ProductService implements IProductService { + + private static List productList = new ArrayList<>(); + + static { + for (int i = 0; i < 20; i++) { + productList.add(new Product(i, "产品" + i, i / 2 == 0, new Date(), 66.66f * i)); + } + } + + public Product queryProductById(int id) { + for (Product product : productList) { + if (product.getId() == id) { + return product; + } + } + return null; + } + + + public List queryAllProducts() { + return productList; + } +} +``` + +#### 4.2 在dubbo.xml暴露服务 + +```xml + + + + + + + + + + + + + + + + + + +``` + +## 五、服务消费者(dubbo-consumer) + +![spring-scheduling](D:\spring-samples-for-all\pictures\dubbo-consumer.png) + +#### 1.在dubbo.xml调用远程的服务 + +```xml + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.消费服务 + +```java +@Controller +@RequestMapping("sell") +public class SellController { + + @Autowired + private IProductService productService; + + @RequestMapping + public String productList(Model model) { + List products = productService.queryAllProducts(); + model.addAttribute("products", products); + return "products"; + } + + @RequestMapping("product/{id}") + public String productDetail(@PathVariable int id, Model model) { + Product product = productService.queryProductById(id); + model.addAttribute("product", product); + return "product"; + } +} +``` + +## 六、项目构建的说明 + +因为在项目中,consumer和provider模块均依赖公共模块,所以在构建consumer和provider项目前需要将common 模块安装到本地仓库,**依次**对**父工程**和**common模块**执行: + +```shell +mvn install -Dmaven.test.skip = true +``` + +consumer中 pom.xml如下 + +```xml + + + + spring-dubbo + com.heibaiying + 1.0-SNAPSHOT + + 4.0.0 + + dubbo-consumer + + + + com.heibaiying + dubbo-common + 1.0-SNAPSHOT + compile + + + + +``` + +provider中 pom.xml如下 + +```xml + + + + spring-dubbo + com.heibaiying + 1.0-SNAPSHOT + + 4.0.0 + + dubbo-provider + + + + com.heibaiying + dubbo-common + 1.0-SNAPSHOT + compile + + + + +``` + +## 七、关于dubbo新版本管理控制台的安装说明 + +安装: + +```sh +git clone https://github.com/apache/incubator-dubbo-ops.git /var/tmp/dubbo-ops +cd /var/tmp/dubbo-ops +mvn clean package +``` + +配置: + +```sh +配置文件为: +dubbo-admin-backend/src/main/resources/application.properties +主要的配置有 默认的配置就是127.0.0.1:2181: +dubbo.registry.address=zookeeper://127.0.0.1:2181 +``` + +启动: + +```sh +mvn --projects dubbo-admin-backend spring-boot:run +``` + +访问: + +``` +http://127.0.0.1:8080 +``` \ No newline at end of file diff --git a/spring/spring-email-annotation/README.md b/spring/spring-email-annotation/README.md new file mode 100644 index 0000000..2e0cfc9 --- /dev/null +++ b/spring/spring-email-annotation/README.md @@ -0,0 +1,287 @@ +# spring 邮件发送(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 邮件发送配置类为com.heibaiying.config下EmailConfig.java; +2. 简单邮件发送、附件邮件发送、内嵌资源邮件发送、模板邮件发送的方法封装在SpringMail类中; +3. 项目以单元测试的方法进行测试,测试类为SendEmail。 + + + +![spring-email](D:\spring-samples-for-all\pictures\spring-email-annotation.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入邮件发送的支持包spring-context-support + +```xml + + + org.springframework + spring-context-support + ${spring-base-version} + + + + + com.ibeetl + beetl + 2.9.7 + +``` + + + +## 二、spring email + +#### 2.1 邮件发送配置 + +```java +/** + * @author : heibaiying + * @description : 邮件发送配置类 + */ + +@Configuration +@ComponentScan(value = "com.heibaiying.email") +public class EmailConfig { + + /*** + * 在这里可以声明不同的邮件服务器主机,通常是SMTP主机,而具体的用户名和时授权码则建议在业务中从数据库查询 + */ + @Bean(name = "qqMailSender") + JavaMailSenderImpl javaMailSender() { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + javaMailSender.setHost("smtp.qq.com"); + javaMailSender.setPassword("587"); + return javaMailSender; + } + + /*** + * 配置模板引擎 + */ + @Bean + GroupTemplate groupTemplate() throws IOException { + //指定加载模板资源的位置 指定在classpath:beetl下- + ClasspathResourceLoader loader = new ClasspathResourceLoader("beetl"); + //beetl配置 这里采用默认的配置- + org.beetl.core.Configuration configuration = org.beetl.core.Configuration.defaultConfiguration(); + return new GroupTemplate(loader, configuration); + } +} + +``` + +#### 2.2 新建邮件发送基本类 + +```java +/** + * @author : heibaiying + * @description : 邮件发送基本类 + */ +@Component +public class SpringMail { + + @Autowired + private JavaMailSenderImpl qqMailSender; + @Autowired + private GroupTemplate groupTemplate; + + /** + * 发送简单邮件 + * 在qq邮件发送的测试中,测试结果表明不管是简单邮件还是复杂邮件都必须指定发送用户, + * 且发送用户已经授权不然都会抛出异常: SMTPSendFailedException 501 mail from address must be same as authorization user + * qq 的授权码 可以在 设置/账户/POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 中开启服务后获取 + */ + public void sendTextMessage(String from, String authWord, String to, String subject, String content) { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + SimpleMailMessage msg = new SimpleMailMessage(); + msg.setFrom(from); + msg.setTo(to); + msg.setSubject(subject); + msg.setText(content); + try { + // 发送消息 + this.qqMailSender.send(msg); + System.out.println("发送邮件成功"); + } catch (MailException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + /** + * 发送带附件的邮件 + */ + public void sendEmailWithAttachments(String from, String authWord, String to, + String subject, String content, Map files) { + try { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 需要指定第二个参数为true 代表创建支持可选文本,内联元素和附件的多部分消息 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content); + // 传入附件 + for (Map.Entry entry : files.entrySet()) { + helper.addAttachment(entry.getKey(), entry.getValue()); + } + // 发送消息 + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + + /** + * 发送带内嵌资源的邮件 + */ + public void sendEmailWithInline(String from, String authWord, String to, + String subject, String content, File file) { + try { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 需要指定第二个参数为true 代表创建支持可选文本,内联元素和附件的多部分消息 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + // 使用true标志来指示包含的文本是HTML 固定格式资源前缀 cid: + helper.setText("", true); + // 需要先指定文本 再指定资源文件 + FileSystemResource res = new FileSystemResource(file); + helper.addInline("image", res); + // 发送消息 + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + /** + * 使用模板邮件 + */ + public void sendEmailByTemplate(String from, String authWord, String to, + String subject, String content) { + try { + Template t = groupTemplate.getTemplate("template.html"); + t.binding("subject", subject); + t.binding("content", content); + String text = t.render(); + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 指定 utf-8 防止乱码 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + // 为true 时候 表示文本内容以 html 渲染 + helper.setText(text, true); + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + +} + +``` + +**关于模板邮件的说明:** + +- 模板引擎最主要的作用是,在对邮件格式有要求的时候,采用拼接字符串不够直观,所以采用模板引擎; + +- 这里我们使用的beetl模板引擎,原因是其性能优异,官网是介绍其性能6倍与freemaker,并有完善的文档支持。当然大家也可以换成任何其他的模板引擎(freemarker,thymeleaf) + + 一个简单的模板template.html如下: + +```html + + + + + + +

邮件主题: ${subject}

+

${content}

+ + +``` + + + +#### 2.3 邮件发送的测试 + +```java +/** + * @author : heibaiying + * @description : 发送邮件测试类 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = EmailConfig.class) +public class SendEmail { + + @Autowired + private SpringMail springMail; + + // 发送方邮箱地址 + private static final String from = "发送方邮箱地址@qq.com"; + // 发送方邮箱地址对应的授权码 + private static final String authWord = "授权码"; + // 接收方邮箱地址 + private static final String to = "接收方邮箱地址@qq.com"; + + @Test + public void sendMessage() { + + springMail.sendTextMessage(from, authWord, to, "spring简单邮件", "Hello Spring Email!"); + } + + + @Test + public void sendComplexMessage() { + Map fileMap = new HashMap<>(); + fileMap.put("image1.jpg", new File("D:\\LearningNotes\\picture\\msm相关依赖.png")); + fileMap.put("image2.jpg", new File("D:\\LearningNotes\\picture\\RabbitMQ模型架构.png")); + springMail.sendEmailWithAttachments(from, authWord, to, "spring多附件邮件" + , "Hello Spring Email!", fileMap); + } + + @Test + public void sendEmailWithInline() { + springMail.sendEmailWithInline(from, authWord, to, "spring内嵌资源邮件" + , "Hello Spring Email!", new File("D:\\LearningNotes\\picture\\RabbitMQ模型架构.png")); + } + + @Test + public void sendEmailByTemplate() { + springMail.sendEmailByTemplate(from, authWord, to, + "spring模板邮件", "Hello Spring Email!"); + } +} +``` diff --git a/spring/spring-email-annotation/src/main/java/com/heibaiying/config/EmailConfig.java b/spring/spring-email-annotation/src/main/java/com/heibaiying/config/EmailConfig.java index cdf5bec..1eede89 100644 --- a/spring/spring-email-annotation/src/main/java/com/heibaiying/config/EmailConfig.java +++ b/spring/spring-email-annotation/src/main/java/com/heibaiying/config/EmailConfig.java @@ -11,7 +11,7 @@ import java.io.IOException; /** * @author : heibaiying - * @description : + * @description : 邮件发送配置类 */ @Configuration diff --git a/spring/spring-email/README.md b/spring/spring-email/README.md new file mode 100644 index 0000000..1eff4b8 --- /dev/null +++ b/spring/spring-email/README.md @@ -0,0 +1,298 @@ +# spring 邮件发送(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 邮件发送配置文件为springApplication.xml; +2. 简单邮件发送、附件邮件发送、内嵌资源邮件发送、模板邮件发送的方法封装在SpringMail类中; +3. 项目以单元测试的方法进行测试,测试类为SendEmail。 + + + +![spring-email](D:\spring-samples-for-all\pictures\spring-email.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入邮件发送的支持包spring-context-support + +```xml + + + org.springframework + spring-context-support + ${spring-base-version} + + + + + com.ibeetl + beetl + 2.9.7 + +``` + + + +## 二、spring email + +#### 2.1 邮件发送配置 + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.2 新建邮件发送基本类 + +```java +/** + * @author : heibaiying + * @description : 邮件发送基本类 + */ +@Component +public class SpringMail { + + @Autowired + private JavaMailSenderImpl qqMailSender; + @Autowired + private GroupTemplate groupTemplate; + + /** + * 发送简单邮件 + * 在qq邮件发送的测试中,测试结果表明不管是简单邮件还是复杂邮件都必须指定发送用户, + * 且发送用户已经授权不然都会抛出异常: SMTPSendFailedException 501 mail from address must be same as authorization user + * qq 的授权码 可以在 设置/账户/POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 中开启服务后获取 + */ + public void sendTextMessage(String from, String authWord, String to, String subject, String content) { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + SimpleMailMessage msg = new SimpleMailMessage(); + msg.setFrom(from); + msg.setTo(to); + msg.setSubject(subject); + msg.setText(content); + try { + // 发送消息 + this.qqMailSender.send(msg); + System.out.println("发送邮件成功"); + } catch (MailException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + /** + * 发送带附件的邮件 + */ + public void sendEmailWithAttachments(String from, String authWord, String to, + String subject, String content, Map files) { + try { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 需要指定第二个参数为true 代表创建支持可选文本,内联元素和附件的多部分消息 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content); + // 传入附件 + for (Map.Entry entry : files.entrySet()) { + helper.addAttachment(entry.getKey(), entry.getValue()); + } + // 发送消息 + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + + /** + * 发送带内嵌资源的邮件 + */ + public void sendEmailWithInline(String from, String authWord, String to, + String subject, String content, File file) { + try { + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 需要指定第二个参数为true 代表创建支持可选文本,内联元素和附件的多部分消息 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + // 使用true标志来指示包含的文本是HTML 固定格式资源前缀 cid: + helper.setText("", true); + // 需要先指定文本 再指定资源文件 + FileSystemResource res = new FileSystemResource(file); + helper.addInline("image", res); + // 发送消息 + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + + /** + * 使用模板邮件 + */ + public void sendEmailByTemplate(String from, String authWord, String to, + String subject, String content) { + try { + Template t = groupTemplate.getTemplate("template.html"); + t.binding("subject", subject); + t.binding("content", content); + String text = t.render(); + // 设置发送人邮箱和授权码 + qqMailSender.setUsername(from); + qqMailSender.setPassword(authWord); + // 实例化消息对象 + MimeMessage message = qqMailSender.createMimeMessage(); + // 指定 utf-8 防止乱码 + MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + // 为true 时候 表示文本内容以 html 渲染 + helper.setText(text, true); + this.qqMailSender.send(message); + System.out.println("发送邮件成功"); + } catch (MessagingException ex) { + // 消息发送失败可以做对应的处理 + System.err.println("发送邮件失败" + ex.getMessage()); + } + } + +} + +``` + +**关于模板邮件的说明:** + +- 模板引擎最主要的作用是,在对邮件格式有要求的时候,采用拼接字符串不够直观,所以采用模板引擎; + +- 这里我们使用的beetl模板引擎,原因是其性能优异,官网是介绍其性能6倍与freemaker,并有完善的文档支持。当然大家也可以换成任何其他的模板引擎(freemarker,thymeleaf) + + 一个简单的模板template.html如下: + +```html + + + + + + +

邮件主题: ${subject}

+

${content}

+ + +``` + + + +#### 2.3 邮件发送的测试 + +```java +/** + * @author : heibaiying + * @description : 发送邮件测试类 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration({"classpath:springApplication.xml"}) +public class SendEmail { + + @Autowired + private SpringMail springMail; + + // 发送方邮箱地址 + private static final String from = "发送方邮箱地址@qq.com"; + // 发送方邮箱地址对应的授权码 + private static final String authWord = "授权码"; + // 接收方邮箱地址 + private static final String to = "接收方邮箱地址@qq.com"; + + + /** + * 简单邮件测试 + */ + @Test + public void sendMessage() { + springMail.sendTextMessage(from, authWord, to, "spring简单邮件", "Hello Spring Email!"); + } + + /** + * 发送带附件的邮件 + */ + @Test + public void sendComplexMessage() { + Map fileMap = new HashMap<>(); + fileMap.put("image1.jpg", new File("D:\\LearningNotes\\picture\\msm相关依赖.png")); + fileMap.put("image2.jpg", new File("D:\\LearningNotes\\picture\\RabbitMQ模型架构.png")); + springMail.sendEmailWithAttachments(from, authWord, to, "spring多附件邮件" + , "Hello Spring Email!", fileMap); + } + + /** + * 发送内嵌资源的邮件 + */ + @Test + public void sendEmailWithInline() { + springMail.sendEmailWithInline(from, authWord, to, "spring内嵌资源邮件" + , "Hello Spring Email!", new File("D:\\LearningNotes\\picture\\RabbitMQ模型架构.png")); + } + + /** + * 发送模板邮件 + */ + @Test + public void sendEmailByTemplate() { + springMail.sendEmailByTemplate(from, authWord, to, + "spring模板邮件", "Hello Spring Email!"); + } +} + +``` diff --git a/spring/spring-email/src/main/java/com/heibaiying/email/SpringMail.java b/spring/spring-email/src/main/java/com/heibaiying/email/SpringMail.java index 31229ca..74d5f84 100644 --- a/spring/spring-email/src/main/java/com/heibaiying/email/SpringMail.java +++ b/spring/spring-email/src/main/java/com/heibaiying/email/SpringMail.java @@ -17,7 +17,7 @@ import java.util.Map; /** * @author : heibaiying - * @description : + * @description : 邮件发送基本类 */ @Component public class SpringMail { diff --git a/spring/spring-email/src/main/resources/springApplication.xml b/spring/spring-email/src/main/resources/springApplication.xml index cf5b2d6..5a12d3e 100644 --- a/spring/spring-email/src/main/resources/springApplication.xml +++ b/spring/spring-email/src/main/resources/springApplication.xml @@ -17,7 +17,7 @@ - + diff --git a/spring/spring-email/src/test/java/com/heibaiying/SendEmail.java b/spring/spring-email/src/test/java/com/heibaiying/SendEmail.java index da654cd..2e96161 100644 --- a/spring/spring-email/src/test/java/com/heibaiying/SendEmail.java +++ b/spring/spring-email/src/test/java/com/heibaiying/SendEmail.java @@ -29,13 +29,19 @@ public class SendEmail { // 接收方邮箱地址 private static final String to = "接收方邮箱地址@qq.com"; + + /** + * 简单邮件测试 + */ @Test public void sendMessage() { - springMail.sendTextMessage(from, authWord, to, "spring简单邮件", "Hello Spring Email!"); } + /** + * 发送带附件的邮件 + */ @Test public void sendComplexMessage() { Map fileMap = new HashMap<>(); @@ -45,12 +51,18 @@ public class SendEmail { , "Hello Spring Email!", fileMap); } + /** + * 发送内嵌资源的邮件 + */ @Test public void sendEmailWithInline() { springMail.sendEmailWithInline(from, authWord, to, "spring内嵌资源邮件" , "Hello Spring Email!", new File("D:\\LearningNotes\\picture\\RabbitMQ模型架构.png")); } + /** + * 发送模板邮件 + */ @Test public void sendEmailByTemplate() { springMail.sendEmailByTemplate(from, authWord, to, diff --git a/spring/spring-memcached-annotation/README.md b/spring/spring-memcached-annotation/README.md new file mode 100644 index 0000000..5254836 --- /dev/null +++ b/spring/spring-memcached-annotation/README.md @@ -0,0 +1,150 @@ +# spring 整合 mecached(注解方式) + +## 一、说明 + +### 1.1 XMemcached客户端说明 + +XMemcached是基于java nio的memcached高性能客户端,支持完整的memcached协议,支持客户端分布并且提供了一致性哈希(consistent hash)算法的实现。 + +### 1.2 项目结构说明 + +1. memcached的整合配置位于com.heibaiying.config文件夹下。 + +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-memcached-annotation.png) + +### 1.3 依赖说明 + +除了spring的基本依赖外,需要导入xmemcached依赖包 + +```xml + + + com.googlecode.xmemcached + xmemcached + 2.4.5 + +``` + + + +## 二、spring 整合 memcached + +#### 2.1 单机配置 + +```java +@Bean +public MemcachedClient memcachedClient() { + XMemcachedClientBuilder builder = new XMemcachedClientBuilder("192.168.200.201:11211"); + MemcachedClient memcachedClient = null; +try { + memcachedClient = builder.build(); + } catch (IOException e) { + e.printStackTrace(); +} + return memcachedClient; +} +``` + +#### 2.2 集群配置 + +```java +@Bean +public MemcachedClient memcachedClientForCluster() { + + List addressList = new ArrayList(); + addressList.add(new InetSocketAddress("192.168.200.201", 11211)); + addressList.add(new InetSocketAddress("192.168.200.201", 11212)); + // 赋予权重 + int[] weights = {1, 2}; + XMemcachedClientBuilder builder = new XMemcachedClientBuilder(addressList, weights); + // 设置连接池大小 + builder.setConnectionPoolSize(10); + // 协议工厂 + builder.setCommandFactory(new TextCommandFactory()); + // 分布策略,一致性哈希KetamaMemcachedSessionLocator或者ArraySessionLocator(默认) + builder.setSessionLocator(new KetamaMemcachedSessionLocator()); + // 设置序列化器 + builder.setTranscoder(new SerializingTranscoder()); + MemcachedClient memcachedClient = null; + try { + memcachedClient = builder.build(); + } catch (IOException e) { + e.printStackTrace(); + } + return memcachedClient; +} +``` + +#### 2.3 存储基本类型测试用例 + +xmemcached单机版本和集群版本注入的实例是相同的; + +```java +/** + * @author : heibaiying + * @description : Memcached 操作基本对象 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {MemcacheConfig.class}) +public class MemSamples { + + @Autowired + private MemcachedClient memcachedClient; + + @Test + public void operate() throws InterruptedException, MemcachedException, TimeoutException { + memcachedClient.set("hello", 0, "Hello,cluster xmemcached"); + String value = memcachedClient.get("hello"); + System.out.println("hello=" + value); + memcachedClient.delete("hello"); + value = memcachedClient.get("hello"); + System.out.println("hello=" + value); + } +} +``` + +#### 2.5 存储实体对象测试用例 + +```java +/** + * @author : heibaiying + * @description :Memcached 序列化与反序列化 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {MemcacheConfig.class}) +public class MemObjectSamples { + + @Autowired + private MemcachedClient memcachedClient; + + @Test + public void operate() throws InterruptedException, MemcachedException, TimeoutException { + memcachedClient.set("programmer", 0, new Programmer("xiaoming", 12, 5000.21f, new Date())); + Programmer programmer = memcachedClient.get("programmer"); + System.out.println("hello ," + programmer.getName()); + memcachedClient.delete("programmer"); + programmer = memcachedClient.get("programmer"); + Assert.assertNull(programmer); + } +} + +``` + + + +## 附:memcached 基本命令 + +| 命令 | 格式 | 说明 | +| --------------- | -------------------------------------------------- | ------------------------------------- | +| 新增 set | set key flags exTime length -> value | 无论什么情况,都可以插入 | +| 新增 add | add key flags exTime length -> value | 只有当key不存在的情况下,才可以插入 | +| 替换 replace | replace key flags exTime length -> value | 只修改已存在key的value值 | +| 追加内容append | append key flags exTime length -> value | length表示追加的长度而不是总长度 | +| 前面追加prepend | prepend key flags exTime length -> value | length表示追加的长度而不是总长度 | +| 查询操作 get | get key | | +| 检查更新 cas | cas key flags exTime length version -> value | 版本正确才更新 | +| 详细获取 gets | gets key | 返回的最后一个数代表 key 的 CAS 令牌 | +| 删除 delete | delete key | 将数据打一个删除标记 | +| 自增 incr | incr key 增加偏移量 | incr和decr只能操作能转换为数字的Value | +| 自减 decr | decr key 减少偏移量 | desr不能将数字减少至0以下 | +| 清库 | flush_all | | \ No newline at end of file diff --git a/spring/spring-memcached/README.md b/spring/spring-memcached/README.md new file mode 100644 index 0000000..0615160 --- /dev/null +++ b/spring/spring-memcached/README.md @@ -0,0 +1,191 @@ +# spring 整合 mecached(xml配置方式) + +## 一、说明 + +### 1.1 XMemcached客户端说明 + +XMemcached是基于java nio的memcached高性能客户端,支持完整的memcached协议,支持客户端分布并且提供了一致性哈希(consistent hash)算法的实现。 + +### 1.2 项目结构说明 + +1. memcached的整合配置位于resources下的memcached文件夹下,其中集群配置用cluster开头。所有配置按照需要在springApplication.xml用import导入。 +2. 实体类Programmer.java用于测试memcached序列化与反序列化 + +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-memcached.png) + +**springapplication.xml文件:** + +```xml + + + + + + + + + + +``` + +### 1.3 依赖说明 + +除了spring的基本依赖外,需要导入xmemcached依赖包 + +```xml + + + com.googlecode.xmemcached + xmemcached + 2.4.5 + +``` + + + +## 二、spring 整合 memcached + +#### 2.1 单机配置 + +```xml + + + + + + + + + + +``` + +#### 2.2 集群配置 + +```xml + + + + + + + + + + + + + + + + + + + + + 1 + 2 + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.3 存储基本类型测试用例 + +xmemcached单机版本和集群版本注入的实例是相同的; + +```java +/** + * @author : heibaiying + * @description : Memcached 操作基本对象 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration({"classpath:springApplication.xml"}) +public class MemSamples { + + @Autowired + private MemcachedClient memcachedClient; + + @Test + public void operate() throws InterruptedException, MemcachedException, TimeoutException { + memcachedClient.set("hello", 0, "Hello,cluster xmemcached"); + String value = memcachedClient.get("hello"); + System.out.println("hello=" + value); + memcachedClient.delete("hello"); + value = memcachedClient.get("hello"); + System.out.println("hello=" + value); + } +} + +``` + +#### 2.5 存储实体对象测试用例 + +```java +/** + * @author : heibaiying + * @description :Memcached 序列化与反序列化 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration({"classpath:springApplication.xml"}) +public class MemObjectSamples { + + @Autowired + private MemcachedClient memcachedClient; + + @Test + public void operate() throws InterruptedException, MemcachedException, TimeoutException { + memcachedClient.set("programmer", 0, new Programmer("xiaoming", 12, 5000.21f, new Date())); + Programmer programmer = memcachedClient.get("programmer"); + System.out.println("hello ," + programmer.getName()); + memcachedClient.delete("programmer"); + programmer = memcachedClient.get("programmer"); + Assert.assertNull(programmer); + } +} + +``` + + + +## 附:memcached 基本命令 + +| 命令 | 格式 | 说明 | +| --------------- | -------------------------------------------------- | ------------------------------------- | +| 新增 set | set key flags exTime length -> value | 无论什么情况,都可以插入 | +| 新增 add | add key flags exTime length -> value | 只有当key不存在的情况下,才可以插入 | +| 替换 replace | replace key flags exTime length -> value | 只修改已存在key的value值 | +| 追加内容append | append key flags exTime length -> value | length表示追加的长度而不是总长度 | +| 前面追加prepend | prepend key flags exTime length -> value | length表示追加的长度而不是总长度 | +| 查询操作 get | get key | | +| 检查更新 cas | cas key flags exTime length version -> value | 版本正确才更新 | +| 详细获取 gets | gets key | 返回的最后一个数代表 key 的 CAS 令牌 | +| 删除 delete | delete key | 将数据打一个删除标记 | +| 自增 incr | incr key 增加偏移量 | incr和decr只能操作能转换为数字的Value | +| 自减 decr | decr key 减少偏移量 | desr不能将数字减少至0以下 | +| 清库 | flush_all | | \ No newline at end of file diff --git a/spring/spring-mongodb-annotation/README.md b/spring/spring-mongodb-annotation/README.md new file mode 100644 index 0000000..aec50c7 --- /dev/null +++ b/spring/spring-mongodb-annotation/README.md @@ -0,0 +1,161 @@ +# spring 整合 mongodb(注解方式) + +## 一、说明 + +### 1.1 项目结构说明 + +配置文件位于com.heibaiying.config下,项目以单元测试的方式进行测试。 + +![spring-mongodb-annotation](D:\spring-samples-for-all\pictures\spring-mongodb-annotation.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入mongodb整合依赖包 + +```xml + + + org.springframework.data + spring-data-mongodb + 2.1.3.RELEASE + +``` + + + +## 二、spring mongodb + +#### 2.1 新建配置文件及其映射类 + +```properties +mongo.host=192.168.200.228 +mongo.port=27017 +# 数据库名称. 默认是'db'. +mongo.dbname=database +# 每个主机允许的连接数 +mongo.connectionsPerHost=10 +# 线程队列数,它和上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出异常 +mongo.threadsAllowedToBlockForConnectionMultiplier=5 +# 连接超时的毫秒 0是默认值且无限大。 +mongo.connectTimeout=1000 +# 最大等待连接的线程阻塞时间 默认是120000 ms (2 minutes). +mongo.maxWaitTime=1500 +# 保持活动标志,控制是否有套接字保持活动超时 官方默认为true 且不建议禁用 +mongo.socketKeepAlive=true +# 用于群集心跳的连接的套接字超时。 +mongo.socketTimeout=1500 +``` + +```java +/** + * @author : heibaiying + * @description : Mongo 配置属性 + */ +@Data +@Configuration +@PropertySource(value = "classpath:mongodb.properties") +public class MongoProperty { + + @Value("${mongo.host}") + private String host; + @Value("${mongo.port}") + private int port; + @Value("${mongo.dbname}") + private String dbname; + @Value("${mongo.connectionsPerHost}") + private int connectionsPerHost; + @Value("${mongo.threadsAllowedToBlockForConnectionMultiplier}") + private int multiplier; + @Value("${mongo.connectTimeout}") + private int connectTimeout; + @Value("${mongo.maxWaitTime}") + private int maxWaitTime; + @Value("${mongo.socketKeepAlive}") + private boolean socketKeepAlive; + @Value("${mongo.socketTimeout}") + private int socketTimeout; +} +``` + +#### 2.2 整合配置 + +```java +/** + * @author : heibaiying + * @description : Mongo 配置类 + */ + +@Configuration +@ComponentScan(value = "com.heibaiying.*") +public class MongoConfig { + + @Bean + public MongoDbFactory mongoDbFactory(MongoProperty mongo) { + MongoClientOptions options = MongoClientOptions.builder() + .threadsAllowedToBlockForConnectionMultiplier(mongo.getMultiplier()) + .connectionsPerHost(mongo.getConnectionsPerHost()) + .connectTimeout(mongo.getConnectTimeout()) + .maxWaitTime(mongo.getMaxWaitTime()) + .socketTimeout(mongo.getSocketTimeout()) + .build(); + MongoClient client = new MongoClient(new ServerAddress(mongo.getHost(), mongo.getPort()), options); + return new SimpleMongoDbFactory(client, mongo.getDbname()); + } + + @Bean + public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory) { + return new MongoTemplate(mongoDbFactory); + } +} +``` + +#### 2.3 测试整合 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = MongoConfig.class) +public class MongoDBTest { + + @Autowired + private MongoTemplate mongoTemplate; + + @Test + public void insert() { + // 单条插入 + mongoTemplate.insert(new Programmer("xiaoming", 12, 5000.21f, new Date())); + List programmers = new ArrayList(); + // 批量插入 + programmers.add(new Programmer("xiaohong", 21, 52200.21f, new Date())); + programmers.add(new Programmer("xiaolan", 34, 500.21f, new Date())); + mongoTemplate.insert(programmers, Programmer.class); + } + + // 条件查询 + @Test + public void select() { + Criteria criteria = new Criteria(); + criteria.andOperator(where("name").is("xiaohong"), where("age").is(21)); + Query query = new Query(criteria); + Programmer one = mongoTemplate.findOne(query, Programmer.class); + System.out.println(one); + } + + + // 更新数据 + @Test + public void MUpdate() { + UpdateResult updateResult = mongoTemplate.updateMulti(query(where("name").is("xiaoming")), update("age", 35), Programmer.class); + System.out.println("更新记录数:" + updateResult.getModifiedCount()); + } + + // 删除指定数据 + @Test + public void delete() { + DeleteResult result = mongoTemplate.remove(query(where("name").is("xiaolan")), Programmer.class); + System.out.println("影响记录数:" + result.getDeletedCount()); + System.out.println("是否成功:" + result.wasAcknowledged()); + } +} +``` diff --git a/spring/spring-mongodb/README.md b/spring/spring-mongodb/README.md new file mode 100644 index 0000000..7f5d03d --- /dev/null +++ b/spring/spring-mongodb/README.md @@ -0,0 +1,144 @@ +# spring 整合 mongodb(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +配置文件位于resources下,项目以单元测试的方式进行测试。 + +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-mongodb.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入mongodb整合依赖包 + +```xml + + + org.springframework.data + spring-data-mongodb + 2.1.3.RELEASE + +``` + + + +## 二、spring mongodb + +#### 2.1 新建配置文件 + +```properties +mongo.host=192.168.200.228 +mongo.port=27017 +# 数据库名称. 默认是'db'. +mongo.dbname=database +# 每个主机允许的连接数 +mongo.connectionsPerHost=10 +# 线程队列数,它和上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出异常 +mongo.threadsAllowedToBlockForConnectionMultiplier=5 +# 连接超时的毫秒 0是默认值且无限大。 +mongo.connectTimeout=1000 +# 最大等待连接的线程阻塞时间 默认是120000 ms (2 minutes). +mongo.maxWaitTime=1500 +# 保持活动标志,控制是否有套接字保持活动超时 官方默认为true 且不建议禁用 +mongo.socketKeepAlive=true +# 用于群集心跳的连接的套接字超时。 +mongo.socketTimeout=1500 +``` + +#### 2.2 整合配置 + +```xml + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.3 测试整合 + +```java +/** + * @author : heibaiying + * @description : MongoDB 查询 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(locations = "classpath:mongodb.xml") +public class MongoDBTest { + + @Autowired + private MongoTemplate mongoTemplate; + + @Test + public void insert() { + // 单条插入 + mongoTemplate.insert(new Programmer("xiaoming", 12, 5000.21f, new Date())); + List programmers = new ArrayList(); + // 批量插入 + programmers.add(new Programmer("xiaohong", 21, 52200.21f, new Date())); + programmers.add(new Programmer("xiaolan", 34, 500.21f, new Date())); + mongoTemplate.insert(programmers, Programmer.class); + } + + // 条件查询 + @Test + public void select() { + Criteria criteria = new Criteria(); + criteria.andOperator(where("name").is("xiaohong"), where("age").is(21)); + Query query = new Query(criteria); + Programmer one = mongoTemplate.findOne(query, Programmer.class); + System.out.println(one); + } + + + // 更新数据 + @Test + public void MUpdate() { + UpdateResult updateResult = mongoTemplate.updateMulti(query(where("name").is("xiaoming")), update("age", 35), Programmer.class); + System.out.println("更新记录数:" + updateResult.getModifiedCount()); + } + + // 删除指定数据 + @Test + public void delete() { + DeleteResult result = mongoTemplate.remove(query(where("name").is("xiaolan")), Programmer.class); + System.out.println("影响记录数:" + result.getDeletedCount()); + System.out.println("是否成功:" + result.wasAcknowledged()); + } + +} +``` diff --git a/spring/spring-mongodb/src/main/resources/mongodb.xml b/spring/spring-mongodb/src/main/resources/mongodb.xml index 7db314b..a1f86d8 100644 --- a/spring/spring-mongodb/src/main/resources/mongodb.xml +++ b/spring/spring-mongodb/src/main/resources/mongodb.xml @@ -10,9 +10,10 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + + + + diff --git a/spring/spring-rabbitmq-annotation/README.md b/spring/spring-rabbitmq-annotation/README.md new file mode 100644 index 0000000..8ef27f7 --- /dev/null +++ b/spring/spring-rabbitmq-annotation/README.md @@ -0,0 +1,403 @@ +# spring 整合 rabbitmq(注解方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 本用例关于rabbitmq的整合提供**简单消息发送**和**对象消费发送**两种情况下的sample。 + +2. rabbitBaseAnnotation.java中声明了topic类型的交换机、持久化队列、及其绑定关系,用于测试说明topic交换机路由键的绑定规则。 + +3. rabbitObjectAnnotation.java中声明了direct类型的交换机,持久化队列,及其绑定关系,用于示例对象消息的传输。 + + 注:关于rabbitmq安装、交换机、队列、死信队列等基本概念可以参考我的手记[《RabbitMQ实战指南》读书笔记](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/RabbitMQ/%E3%80%8ARabbitMQ%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md),里面有详细的配图说明。 + + + +![spring-rabbitmq](D:\spring-samples-for-all\pictures\spring-rabbitmq-annotation.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入spring rabbitmq 整合依赖 + +```xml + + + org.springframework.amqp + spring-rabbit + 2.1.2.RELEASE + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.8 + +``` + + + +## 二、spring rabbit 基本配置 + +#### 2.1 基本配置属性及其映射类 + +```properties +rabbitmq.addresses=localhost:5672 +rabbitmq.username=guest +rabbitmq.password=guest +# 虚拟主机,可以类比为命名空间 默认为/ 必须先用图形界面或者管控台添加 程序不会自动创建且会抛出异常 +rabbitmq.virtualhost=/ +``` + +```java +/** + * @author : heibaiying + * @description : rabbit 属性配置 + */ +@Data +@PropertySource(value = "classpath:rabbitmq.properties") +@Configuration +public class RabbitProperty { + + + @Value("${rabbitmq.addresses}") + private String addresses; + + @Value("${rabbitmq.username}") + private String username; + + @Value("${rabbitmq.password}") + private String password; + + @Value("${rabbitmq.virtualhost}") + private String virtualhost; +} +``` + +#### 2.2 创建连接工厂、管理器 + +```java + +@Configuration +@ComponentScan("com.heibaiying.rabbit.config") +public class RabbitBaseConfig { + + /** + * 声明连接工厂 + */ + @Bean + public ConnectionFactory connectionFactory(RabbitProperty property) { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); + connectionFactory.setAddresses(property.getAddresses()); + connectionFactory.setUsername(property.getUsername()); + connectionFactory.setPassword(property.getPassword()); + connectionFactory.setVirtualHost(property.getVirtualhost()); + return connectionFactory; + } + + /** + * 创建一个管理器(org.springframework.amqp.rabbit.core.RabbitAdmin),用于管理交换,队列和绑定。 + * auto-startup 指定是否自动声明上下文中的队列,交换和绑定, 默认值为true。 + */ + @Bean + public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + rabbitAdmin.setAutoStartup(true); + return rabbitAdmin; + } + + + @Bean + public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { + RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + return rabbitTemplate; + } +} +``` + + + +## 三、简单消费的发送 + +#### 3.1 声明交换机、队列、绑定关系和消费者监听器 + +```java +import com.rabbitmq.client.Channel; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author : heibaiying + * @description : 声明队列、交换机、绑定关系、和队列消息监听 + */ + +@Configuration +public class RabbitBaseAnnotation { + + @Bean + public TopicExchange exchange() { + // 创建一个持久化的交换机 + return new TopicExchange("topic01", true, false); + } + + @Bean + public Queue firstQueue() { + // 创建一个持久化的队列1 + return new Queue("FirstQueue", true); + } + + @Bean + public Queue secondQueue() { + // 创建一个持久化的队列2 + return new Queue("SecondQueue", true); + } + + /** + * BindingKey 中可以存在两种特殊的字符串“#”和“*”,其中“*”用于匹配一个单词,“#”用于匹配零个或者多个单词 + * 这里我们声明三个绑定关系用于测试topic这种类型交换器 + */ + @Bean + public Binding orange() { + return BindingBuilder.bind(firstQueue()).to(exchange()).with("*.orange.*"); + } + + @Bean + public Binding rabbit() { + return BindingBuilder.bind(secondQueue()).to(exchange()).with("*.*.rabbit"); + } + + @Bean + public Binding lazy() { + return BindingBuilder.bind(secondQueue()).to(exchange()).with("lazy.#"); + } + + + /*创建队列1消费者监听*/ + @Bean + public SimpleMessageListenerContainer firstQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + // 设置监听的队列 + container.setQueues(firstQueue()); + // 指定要创建的并发使用者数。 + container.setConcurrentConsumers(1); + // 设置消费者数量的上限 + container.setMaxConcurrentConsumers(5); + // 设置是否自动签收消费 为保证消费被成功消费,建议手工签收 + container.setAcknowledgeMode(AcknowledgeMode.MANUAL); + container.setMessageListener(new ChannelAwareMessageListener() { + @Override + public void onMessage(Message message, Channel channel) throws Exception { + // 可以在这个地方得到消息额外属性 + MessageProperties properties = message.getMessageProperties(); + //得到消息体内容 + byte[] body = message.getBody(); + System.out.println(firstQueue().getName() + "收到消息:" + new String(body)); + /* + * DeliveryTag 是一个单调递增的整数 + * 第二个参数 代表是否一次签收多条,如果设置为true,则所有DeliveryTag小于该DeliveryTag的消息都会被签收 + */ + channel.basicAck(properties.getDeliveryTag(), false); + } + }); + return container; + } + + + /*创建队列2消费者监听*/ + @Bean + public SimpleMessageListenerContainer secondQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + container.setQueues(secondQueue()); + container.setMessageListener(new ChannelAwareMessageListener() { + @Override + public void onMessage(Message message, Channel channel) throws Exception { + byte[] body = message.getBody(); + System.out.println(secondQueue().getName() + "收到消息:" + new String(body)); + } + }); + return container; + } + +} +``` + +#### 3.2 测试简单消息的发送 + +```java +/** + * @author : heibaiying + * @description : 传输简单字符串 + */ + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = RabbitBaseConfig.class) +public class RabbitTest { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Test + public void sendMessage() { + MessageProperties properties = new MessageProperties(); + + String allReceived = "我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到"; + Message message1 = new Message(allReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.orange.rabbit", message1); + + String firstReceived = "我的路由键 quick.orange.fox 只符合queue1 的要求,只能被queue 1 接收到"; + Message message2 = new Message(firstReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.orange.fox", message2); + + String secondReceived = "我的路由键 lazy.brown.fox 只符合queue2 的要求,只能被queue 2 接收到"; + Message message3 = new Message(secondReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "lazy.brown.fox", message3); + + String notReceived = "我的路由键 quick.brown.fox 不符合 topic1 任何绑定队列的要求,你将看不到我"; + Message message4 = new Message(notReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.brown.fox", message4); + } +} +``` + +```java +结果: + SecondQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 + FirstQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 + FirstQueue收到消息:我的路由键 quick.orange.fox 只符合queue1 的要求,只能被queue 1 接收到 + SecondQueue收到消息:我的路由键 lazy.brown.fox 只符合queue2 的要求,只能被queue 2 接收到 +``` + + + +## 四、传输对象 + +#### 4.1 创建消息的委托处理器 + +这里为了增强用例的实用性,我们创建的处理器的handleMessage方法是一个重载方法,对于同一个队列的监听,不仅可以传输对象消息,同时针对不同的对象类型调用不同的处理方法。 + +```java +/** + * @author : heibaiying + * @description :消息委派处理类 + */ +public class MessageDelegate { + + public void handleMessage(ProductManager manager) { + System.out.println("收到一个产品经理" + manager); + } + + public void handleMessage(Programmer programmer) { + System.out.println("收到一个程序员" + programmer); + } + +} +``` + +#### 4.2 声明交换机、队列、绑定关系和消费者监听器 + +```java +/** + * @author : heibaiying + * @description : 声明队列、交换机、绑定关系、用于测试对象的消息传递 + */ + +@Configuration +public class RabbitObjectAnnotation { + + @Bean + public DirectExchange objectTopic() { + // 创建一个持久化的交换机 + return new DirectExchange("objectTopic", true, false); + } + + @Bean + public Queue objectQueue() { + // 创建一个持久化的队列 + return new Queue("objectQueue", true); + } + + @Bean + public Binding binding() { + return BindingBuilder.bind(objectQueue()).to(objectTopic()).with("object"); + } + + + /*创建队列消费者监听*/ + @Bean + public SimpleMessageListenerContainer objectQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + // 设置监听的队列 + container.setQueues(objectQueue()); + // 将监听到的消息委派给实际的处理类 + MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); + // 指定由哪个方法来处理消息 默认就是handleMessage + adapter.setDefaultListenerMethod("handleMessage"); + + // 消息转换 + Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); + DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper(); + + Map> idClassMapping = new HashMap<>(); + // 针对不同的消息体调用不同的重载方法 + idClassMapping.put(Type.MANAGER, com.heibaiying.bean.ProductManager.class); + idClassMapping.put(Type.PROGRAMMER, com.heibaiying.bean.Programmer.class); + + javaTypeMapper.setIdClassMapping(idClassMapping); + + jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper); + adapter.setMessageConverter(jackson2JsonMessageConverter); + container.setMessageListener(adapter); + return container; + } + +} +``` + +#### 4.3 测试对象消息的发送 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = RabbitBaseConfig.class) +public class RabbitSendObjectTest { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Test + public void sendProgrammer() throws JsonProcessingException { + MessageProperties messageProperties = new MessageProperties(); + //必须设置 contentType为 application/json + messageProperties.setContentType("application/json"); + // 必须指定类型 + messageProperties.getHeaders().put("__TypeId__", Type.PROGRAMMER); + Programmer programmer = new Programmer("xiaoming", 34, 52200.21f, new Date()); + // 序列化与反序列化都使用的Jackson + ObjectMapper mapper = new ObjectMapper(); + String programmerJson = mapper.writeValueAsString(programmer); + Message message = new Message(programmerJson.getBytes(), messageProperties); + rabbitTemplate.send("objectTopic", "object", message); + } + + + @Test + public void sendProductManager() throws JsonProcessingException { + MessageProperties messageProperties = new MessageProperties(); + messageProperties.setContentType("application/json"); + messageProperties.getHeaders().put("__TypeId__", Type.MANAGER); + ProductManager manager = new ProductManager("xiaohong", 21, new Date()); + ObjectMapper mapper = new ObjectMapper(); + String managerJson = mapper.writeValueAsString(manager); + Message message = new Message(managerJson.getBytes(), messageProperties); + rabbitTemplate.send("objectTopic", "object", message); + } +} +``` \ No newline at end of file diff --git a/spring/spring-rabbitmq-annotation/src/main/java/com/heibaiying/rabbit/RabbitBaseConfig.java b/spring/spring-rabbitmq-annotation/src/main/java/com/heibaiying/rabbit/RabbitBaseConfig.java index c498ce8..c631ed4 100644 --- a/spring/spring-rabbitmq-annotation/src/main/java/com/heibaiying/rabbit/RabbitBaseConfig.java +++ b/spring/spring-rabbitmq-annotation/src/main/java/com/heibaiying/rabbit/RabbitBaseConfig.java @@ -16,7 +16,7 @@ import org.springframework.context.annotation.Configuration; /** * @author : heibaiying - * @description : 声明队列、交换机、绑定关系、和队列消息监听 + * @description : rabbitmq 基本配置 */ @Configuration diff --git a/spring/spring-rabbitmq/README.md b/spring/spring-rabbitmq/README.md new file mode 100644 index 0000000..8c23748 --- /dev/null +++ b/spring/spring-rabbitmq/README.md @@ -0,0 +1,381 @@ +# spring 整合 rabbitmq(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 本用例关于rabbitmq的整合提供**简单消息发送**和**对象消费发送**两种情况下的sample。 + +2. rabbitBaseAnnotation.java中声明了topic类型的交换机、持久化队列、及其绑定关系,用于测试说明topic交换机路由键的绑定规则。 + +3. rabbitObjectAnnotation.java中声明了direct类型的交换机,持久化队列,及其绑定关系,用于示例对象消息的传输。 + + 注:关于rabbitmq安装、交换机、队列、死信队列等基本概念可以参考我的手记[《RabbitMQ实战指南》读书笔记](https://github.com/heibaiying/LearningNotes/blob/master/notes/%E4%B8%AD%E9%97%B4%E4%BB%B6/RabbitMQ/%E3%80%8ARabbitMQ%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md),里面有详细的配图说明。 + + + +![spring-rabbitmq](D:\spring-samples-for-all\pictures\spring-rabbitmq.png) + + + +### 1.2 依赖说明 + +除了spring的基本依赖外,需要导入spring rabbitmq 整合依赖 + +```xml + + + org.springframework.amqp + spring-rabbit + 2.1.2.RELEASE + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.8 + +``` + + + +## 二、spring rabbit 基本配置 + +```properties +rabbitmq.addresses=localhost:5672 +rabbitmq.username=guest +rabbitmq.password=guest +# 虚拟主机,可以类比为命名空间 默认为/ 必须先用图形界面或者管控台添加 程序不会自动创建且会抛出异常 +rabbitmq.virtualhost=/ +``` + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + +## 三、简单消费的发送 + +#### 3.1 声明交换机、队列、绑定关系和消费者监听器 + +```java +import com.rabbitmq.client.Channel; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author : heibaiying + * @description : 声明队列、交换机、绑定关系、和队列消息监听 + */ + +@Configuration +public class RabbitBaseAnnotation { + + @Bean + public TopicExchange exchange() { + // 创建一个持久化的交换机 + return new TopicExchange("topic01", true, false); + } + + @Bean + public Queue firstQueue() { + // 创建一个持久化的队列1 + return new Queue("FirstQueue", true); + } + + @Bean + public Queue secondQueue() { + // 创建一个持久化的队列2 + return new Queue("SecondQueue", true); + } + + /** + * BindingKey 中可以存在两种特殊的字符串“#”和“*”,其中“*”用于匹配一个单词,“#”用于匹配零个或者多个单词 + * 这里我们声明三个绑定关系用于测试topic这种类型交换器 + */ + @Bean + public Binding orange() { + return BindingBuilder.bind(firstQueue()).to(exchange()).with("*.orange.*"); + } + + @Bean + public Binding rabbit() { + return BindingBuilder.bind(secondQueue()).to(exchange()).with("*.*.rabbit"); + } + + @Bean + public Binding lazy() { + return BindingBuilder.bind(secondQueue()).to(exchange()).with("lazy.#"); + } + + + /*创建队列1消费者监听*/ + @Bean + public SimpleMessageListenerContainer firstQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + // 设置监听的队列 + container.setQueues(firstQueue()); + // 指定要创建的并发使用者数。 + container.setConcurrentConsumers(1); + // 设置消费者数量的上限 + container.setMaxConcurrentConsumers(5); + // 设置是否自动签收消费 为保证消费被成功消费,建议手工签收 + container.setAcknowledgeMode(AcknowledgeMode.MANUAL); + container.setMessageListener(new ChannelAwareMessageListener() { + @Override + public void onMessage(Message message, Channel channel) throws Exception { + // 可以在这个地方得到消息额外属性 + MessageProperties properties = message.getMessageProperties(); + //得到消息体内容 + byte[] body = message.getBody(); + System.out.println(firstQueue().getName() + "收到消息:" + new String(body)); + /* + * DeliveryTag 是一个单调递增的整数 + * 第二个参数 代表是否一次签收多条,如果设置为true,则所有DeliveryTag小于该DeliveryTag的消息都会被签收 + */ + channel.basicAck(properties.getDeliveryTag(), false); + } + }); + return container; + } + + + /*创建队列2消费者监听*/ + @Bean + public SimpleMessageListenerContainer secondQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + container.setQueues(secondQueue()); + container.setMessageListener(new ChannelAwareMessageListener() { + @Override + public void onMessage(Message message, Channel channel) throws Exception { + byte[] body = message.getBody(); + System.out.println(secondQueue().getName() + "收到消息:" + new String(body)); + } + }); + return container; + } + +} +``` + +#### 3.2 测试简单消息的发送 + +```java +/** + * @author : heibaiying + * @description : 传输简单字符串 + */ + +@RunWith(SpringRunner.class) +@ContextConfiguration(locations = "classpath:rabbitmq.xml") +public class RabbitTest { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Test + public void sendMessage() { + MessageProperties properties = new MessageProperties(); + + String allReceived = "我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到"; + Message message1 = new Message(allReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.orange.rabbit", message1); + + String firstReceived = "我的路由键 quick.orange.fox 只符合queue1 的要求,只能被queue 1 接收到"; + Message message2 = new Message(firstReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.orange.fox", message2); + + String secondReceived = "我的路由键 lazy.brown.fox 只符合queue2 的要求,只能被queue 2 接收到"; + Message message3 = new Message(secondReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "lazy.brown.fox", message3); + + String notReceived = "我的路由键 quick.brown.fox 不符合 topic1 任何绑定队列的要求,你将看不到我"; + Message message4 = new Message(notReceived.getBytes(), properties); + rabbitTemplate.send("topic01", "quick.brown.fox", message4); + } +} +``` + +```java +结果: + SecondQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 + FirstQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 + FirstQueue收到消息:我的路由键 quick.orange.fox 只符合queue1 的要求,只能被queue 1 接收到 + SecondQueue收到消息:我的路由键 lazy.brown.fox 只符合queue2 的要求,只能被queue 2 接收到 +``` + + + +## 四、传输对象 + +#### 4.1 创建消息的委托处理器 + +这里为了增强用例的实用性,我们创建的处理器的handleMessage方法是一个重载方法,对于同一个队列的监听,不仅可以传输对象消息,同时针对不同的对象类型调用不同的处理方法。 + +```java +/** + * @author : heibaiying + * @description :消息委派处理类 + */ +public class MessageDelegate { + + public void handleMessage(ProductManager manager) { + System.out.println("收到一个产品经理" + manager); + } + + public void handleMessage(Programmer programmer) { + System.out.println("收到一个程序员" + programmer); + } + +} +``` + +#### 4.2 声明交换机、队列、绑定关系和消费者监听器 + +```java +/** + * @author : heibaiying + * @description : 声明队列、交换机、绑定关系、用于测试对象的消息传递 + */ + +@Configuration +public class RabbitObjectAnnotation { + + @Bean + public DirectExchange objectTopic() { + // 创建一个持久化的交换机 + return new DirectExchange("objectTopic", true, false); + } + + @Bean + public Queue objectQueue() { + // 创建一个持久化的队列 + return new Queue("objectQueue", true); + } + + @Bean + public Binding binding() { + return BindingBuilder.bind(objectQueue()).to(objectTopic()).with("object"); + } + + + /*创建队列消费者监听*/ + @Bean + public SimpleMessageListenerContainer objectQueueLister(ConnectionFactory connectionFactory) { + + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + // 设置监听的队列 + container.setQueues(objectQueue()); + // 将监听到的消息委派给实际的处理类 + MessageListenerAdapter adapter = new MessageListenerAdapter(new MessageDelegate()); + // 指定由哪个方法来处理消息 默认就是handleMessage + adapter.setDefaultListenerMethod("handleMessage"); + + // 消息转换 + Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); + DefaultJackson2JavaTypeMapper javaTypeMapper = new DefaultJackson2JavaTypeMapper(); + + Map> idClassMapping = new HashMap<>(); + // 针对不同的消息体调用不同的重载方法 + idClassMapping.put(Type.MANAGER, com.heibaiying.bean.ProductManager.class); + idClassMapping.put(Type.PROGRAMMER, com.heibaiying.bean.Programmer.class); + + javaTypeMapper.setIdClassMapping(idClassMapping); + + jackson2JsonMessageConverter.setJavaTypeMapper(javaTypeMapper); + adapter.setMessageConverter(jackson2JsonMessageConverter); + container.setMessageListener(adapter); + return container; + } + +} +``` + +#### 4.3 测试对象消息的发送 + +```java +@RunWith(SpringRunner.class) +@ContextConfiguration(locations = "classpath:rabbitmq.xml") +public class RabbitSendObjectTest { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Test + public void sendProgrammer() throws JsonProcessingException { + MessageProperties messageProperties = new MessageProperties(); + //必须设置 contentType为 application/json + messageProperties.setContentType("application/json"); + // 必须指定类型 + messageProperties.getHeaders().put("__TypeId__", Type.PROGRAMMER); + Programmer programmer = new Programmer("xiaoming", 34, 52200.21f, new Date()); + // 序列化与反序列化都使用的Jackson + ObjectMapper mapper = new ObjectMapper(); + String programmerJson = mapper.writeValueAsString(programmer); + Message message = new Message(programmerJson.getBytes(), messageProperties); + rabbitTemplate.send("objectTopic", "object", message); + } + + + @Test + public void sendProductManager() throws JsonProcessingException { + MessageProperties messageProperties = new MessageProperties(); + messageProperties.setContentType("application/json"); + messageProperties.getHeaders().put("__TypeId__", Type.MANAGER); + ProductManager manager = new ProductManager("xiaohong", 21, new Date()); + ObjectMapper mapper = new ObjectMapper(); + String managerJson = mapper.writeValueAsString(manager); + Message message = new Message(managerJson.getBytes(), messageProperties); + rabbitTemplate.send("objectTopic", "object", message); + } +} +``` \ No newline at end of file diff --git a/spring/spring-rabbitmq/src/main/java/com/heibaiying/rabbit/RabbitBaseAnnotation.java b/spring/spring-rabbitmq/src/main/java/com/heibaiying/rabbit/RabbitBaseAnnotation.java index 5581346..93b4919 100644 --- a/spring/spring-rabbitmq/src/main/java/com/heibaiying/rabbit/RabbitBaseAnnotation.java +++ b/spring/spring-rabbitmq/src/main/java/com/heibaiying/rabbit/RabbitBaseAnnotation.java @@ -75,7 +75,10 @@ public class RabbitBaseAnnotation { //得到消息体内容 byte[] body = message.getBody(); System.out.println(firstQueue().getName() + "收到消息:" + new String(body)); - //第二个参数 代表是否一次签收多条 + /* + * DeliveryTag 是一个单调递增的整数 + * 第二个参数 代表是否一次签收多条,如果设置为true,则所有DeliveryTag小于该DeliveryTag的消息都会被签收 + */ channel.basicAck(properties.getDeliveryTag(), false); } }); diff --git a/spring/spring-rabbitmq/src/test/java/com/heibaiying/rabbit/RabbitTest.java b/spring/spring-rabbitmq/src/test/java/com/heibaiying/rabbit/RabbitTest.java index 32c408d..0f21a3f 100644 --- a/spring/spring-rabbitmq/src/test/java/com/heibaiying/rabbit/RabbitTest.java +++ b/spring/spring-rabbitmq/src/test/java/com/heibaiying/rabbit/RabbitTest.java @@ -41,7 +41,7 @@ public class RabbitTest { Message message4 = new Message(notReceived.getBytes(), properties); rabbitTemplate.send("topic01", "quick.brown.fox", message4); - /* + /* 结果: * SecondQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 * FirstQueue收到消息:我的路由键 quick.orange.rabbit 符合queue1 和 queue2 的要求,我应该被两个监听器接收到 * FirstQueue收到消息:我的路由键 quick.orange.fox 只符合queue1 的要求,只能被queue 1 接收到 diff --git a/spring/spring-redis-annotation/README.md b/spring/spring-redis-annotation/README.md index c821b72..d893696 100644 --- a/spring/spring-redis-annotation/README.md +++ b/spring/spring-redis-annotation/README.md @@ -24,7 +24,7 @@ 1. jedis和redisson的配置类和单元测试分别位于config和test下对应的包中,其中集群的配置类以cluster开头。 2. 实体类Programmer.java用于测试Redisson序列化与反序列化 -![spring+redis+ano项目目录结构](D:\spring-samples-for-all\pictures\spring+redis+ano项目目录结构.png) +![spring+redis+ano项目目录结构](D:\spring-samples-for-all\pictures\spring-redis-annotation.png) diff --git a/spring/spring-redis/README.md b/spring/spring-redis/README.md index c2c8964..fafd639 100644 --- a/spring/spring-redis/README.md +++ b/spring/spring-redis/README.md @@ -24,7 +24,7 @@ 1. jedis和redisson的配置和单元测试分别位于resources和test下对应的包中,其中集群的配置文件以cluster结尾。所有配置按照需要在springApplication.xml用import导入。 2. 实体类Programmer.java用于测试Redisson序列化与反序列化 -![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring+redis项目目录结构.png) +![spring+redis项目目录结构](D:\spring-samples-for-all\pictures\spring-redis.png) **springapplication.xml文件:** diff --git a/spring/spring-scheduling-annotation/README.md b/spring/spring-scheduling-annotation/README.md new file mode 100644 index 0000000..ddaa651 --- /dev/null +++ b/spring/spring-scheduling-annotation/README.md @@ -0,0 +1,192 @@ +# spring 定时任务(注解方式) + +## 一、说明 + +### 1.1 项目结构说明 + +关于任务的调度配置定义在ServletConfig.java中,为方便观察项目定时执行的情况,项目以web的方式构建。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-scheduling-annotation.png) + + + +### 1.2 依赖说明 + +导入基本依赖 + +```xml + + + 4.0.0 + + com.heibaiying + spring-scheduling + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + 5.1.3.RELEASE + + + + + org.springframework + spring-context + ${spring-base-version} + + + org.springframework + spring-beans + ${spring-base-version} + + + org.springframework + spring-core + ${spring-base-version} + + + org.springframework + spring-web + ${spring-base-version} + + + org.springframework + spring-webmvc + ${spring-base-version} + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + + + +``` + + + +## 二、spring scheduling + +#### 2.1 创建定时任务 + +```java +/** + * @author : heibaiying + */ +@Component +public class Task { + + /** + * 基于间隔的触发器,其中间隔是从上一个任务的 完成时间 开始计算, 时间单位值以毫秒为单位。 + */ + @Scheduled(fixedDelay = 5000, initialDelay = 1000) + public void methodA() { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodA方法执行", LocalDateTime.now())); + } + + /** + * 基于间隔的触发器,其中间隔是从上一个任务的 开始时间 开始测量的。 + */ + @Scheduled(fixedRate = 5000) + @Async + public void methodB() throws InterruptedException { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodB方法执行", LocalDateTime.now())); + Thread.sleep(10 * 1000); + } + + @Scheduled(cron = "0/10 * * * * ?") + public void methodC() { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodC方法执行", LocalDateTime.now())); + } +} + +``` + +#### 2.2 配置定时任务 + +```java +/** + * @author : heibaiying + * spring 主配置类 + */ +@Configuration +@EnableWebMvc +@EnableScheduling //启用Spring的计划任务执行功能 +@EnableAsync //启用Spring的异步方法执行功能 +@ComponentScan(basePackages = {"com.heibaiying.task"}) +public class ServletConfig implements WebMvcConfigurer, AsyncConfigurer, SchedulingConfigurer { + + private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // 任务执行器线程池配置 + @Override + public Executor getAsyncExecutor() { + executor.setCorePoolSize(5); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("MyExecutor-"); + executor.initialize(); + return executor; + } + + // 这个方法可以监听到异步程序发生的错误 + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new AsyncUncaughtExceptionHandler() { + @Override + public void handleUncaughtException(Throwable ex, Method method, Object... params) { + System.out.println(method.getName() + "发生错误:" + ex.getMessage()); + } + }; + } + + // 如果程序结束,需要关闭线程池 不然程序无法完全退出 只能kill才能完全退出 + @PreDestroy + public void destroy() { + if (executor != null) { + executor.shutdown(); + } + } + + // 调度程序线程池配置 + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(taskExecutor()); + } + + // 如果程序结束,需要关闭线程池 + @Bean(destroyMethod = "shutdown") + public Executor taskExecutor() { + return Executors.newScheduledThreadPool(50); + } +} +``` + +**关于调度程序线程池作用说明**: + +按照例子 我们有methodA 、 methodB 、methodC 三个方法 其中 methodB 是耗时的方法如果不声明调度程序线程池 则methodB 会阻塞 methodA 、methodC 方法的执行 因为调度程序是单线程的 + +**关于任务执行线程池作用说明**: + +按照例子 如果我们声明 methodB 是按照 fixedRate=5000 方法执行的 ,理论上不管任务耗时多久,任务都应该是每5秒执行一次,但是实际上任务是被加入执行队列,也不会立即被执行,因为默认执行任务是单线程的,这个时候需要开启@EnableAsync 并指定方法是 @Async 异步的,并且配置执行任务线程池(如果不配置就使用默认的线程池配置) + diff --git a/spring/spring-scheduling/README.md b/spring/spring-scheduling/README.md new file mode 100644 index 0000000..0cf9d90 --- /dev/null +++ b/spring/spring-scheduling/README.md @@ -0,0 +1,183 @@ +# spring 定时任务(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +关于任务的调度配置定义在springApplication.xml中,为方便观察项目定时执行的情况,项目以web的方式构建。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-scheduling.png) + + + +### 1.2 依赖说明 + +导入基本依赖 + +```xml + + + 4.0.0 + + com.heibaiying + spring-scheduling + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + 5.1.3.RELEASE + + + + + org.springframework + spring-context + ${spring-base-version} + + + org.springframework + spring-beans + ${spring-base-version} + + + org.springframework + spring-core + ${spring-base-version} + + + org.springframework + spring-web + ${spring-base-version} + + + org.springframework + spring-webmvc + ${spring-base-version} + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + + + +``` + + + +## 二、spring scheduling + +#### 2.1 创建定时任务 + +```java +package com.heibaiying.task; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; + +import java.time.LocalDateTime; + +/** + * @author : heibaiying + */ +public class Task { + + public void methodA() { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodA方法执行", LocalDateTime.now())); + } + + @Async + public void methodB() throws InterruptedException { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodB方法执行", LocalDateTime.now())); + Thread.sleep(10 * 1000); + } + + public void methodC() { + Thread thread = Thread.currentThread(); + System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", + thread.getName(), thread.getId(), "methodC方法执行", LocalDateTime.now())); + } +} + +``` + +#### 2.2 配置定时任务 + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +**关于调度程序线程池作用说明**: + +按照例子 我们有methodA 、 methodB 、methodC 三个方法 其中 methodB 是耗时的方法如果不声明调度程序线程池 则methodB 会阻塞 methodA 、methodC 方法的执行 因为调度程序是单线程的 + +**关于任务执行线程池作用说明**: + +按照例子 如果我们声明 methodB 是按照 fixedRate=5000 方法执行的 ,理论上不管任务耗时多久,任务都应该是每5秒执行一次,但是实际上任务是被加入执行队列,也不会立即被执行,因为默认执行任务是单线程的,这个时候需要开启@EnableAsync 并指定方法是 @Async 异步的,并且配置执行任务线程池(如果不配置就使用默认的线程池配置) + diff --git a/spring/spring-scheduling/src/main/java/com/heibaiying/task/Task.java b/spring/spring-scheduling/src/main/java/com/heibaiying/task/Task.java index 128e862..653fc57 100644 --- a/spring/spring-scheduling/src/main/java/com/heibaiying/task/Task.java +++ b/spring/spring-scheduling/src/main/java/com/heibaiying/task/Task.java @@ -14,7 +14,6 @@ public class Task { /** * 基于间隔的触发器,其中间隔是从上一个任务的 完成时间 开始计算, 时间单位值以毫秒为单位。 */ - @Scheduled(fixedDelay = 5000, initialDelay = 1000) public void methodA() { Thread thread = Thread.currentThread(); System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", @@ -24,7 +23,6 @@ public class Task { /** * 基于间隔的触发器,其中间隔是从上一个任务的 开始时间 开始测量的。 */ - @Scheduled(fixedRate = 5000) @Async public void methodB() throws InterruptedException { Thread thread = Thread.currentThread(); @@ -33,7 +31,6 @@ public class Task { Thread.sleep(10 * 1000); } - @Scheduled(cron = "0/10 * * * * ?") public void methodC() { Thread thread = Thread.currentThread(); System.out.println(String.format("线程名称:%s ; 线程ID:%s ; 调用方法:%s ; 调用时间:%s", diff --git a/spring/spring-websocket-annotation/README.md b/spring/spring-websocket-annotation/README.md new file mode 100644 index 0000000..1306854 --- /dev/null +++ b/spring/spring-websocket-annotation/README.md @@ -0,0 +1,203 @@ +# spring websocket(注解方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候用临时用户名作为session的id; +2. webconfig 包是基础注解的方式配置web,在spring-base-annotation项目中已经讲解过每个类作用; +3. CustomHander为消息的自定义处理器; +4. CustomHandershakerInterceptor为自定义的 websocket 的握手拦截器; +5. webSocketConfig 是websocket 的主要配置类; +6. 项目以web的方式构建。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-websocket-annotation.png) + + + +### 1.2 依赖说明 + +除了基本的spring 依赖外,还需要导入webSocket的依赖包 + +```xml + + + org.springframework + spring-websocket + 5.1.3.RELEASE + +``` + + + +## 二、spring websocket + +#### 2.1 创建消息处理类,继承自TextWebSocketHandler + +```java +/** + * @author : heibaiying + * @description : 自定义消息处理类 + */ +public class CustomHandler extends TextWebSocketHandler { + + private Map nameAndSession = new ConcurrentHashMap<>(); + + // 建立连接时候触发 + @Override + public void afterConnectionEstablished(WebSocketSession session) { + String username = getNameFromSession(session); + nameAndSession.putIfAbsent(username, session); + } + + + // 关闭连接时候触发 + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { + String username = getNameFromSession(session); + nameAndSession.remove(username); + } + + // 处理消息 + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 防止中文乱码 + String msg = URLDecoder.decode(message.getPayload(), "utf-8"); + String username = getNameFromSession(session); + // 简单模拟群发消息 + TextMessage reply = new TextMessage(username + " : " + msg); + nameAndSession.forEach((s, webSocketSession) + -> { + try { + webSocketSession.sendMessage(reply); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + + private String getNameFromSession(WebSocketSession session) { + Map attributes = session.getAttributes(); + return (String) attributes.get(Constant.USER_NAME); + } +} + +``` + +#### 2.2 创建websocket 握手拦截器(如果没有权限拦截等需求,这一步不是必须的) + +```java +/** + * @author : heibaiying + * @description : 可以按照需求实现权限拦截等功能 + */ +public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { + InetSocketAddress remoteAddress = request.getRemoteAddress(); + InetAddress address = remoteAddress.getAddress(); + System.out.println(address); + /* + * 最后需要要显示调用父类方法,父类的beforeHandshake方法 + * 把ServerHttpRequest 中session中对应的值拷贝到WebSocketSession中。 + * 如果我们没有实现这个方法,我们在最后的handler处理中 是拿不到 session中的值 + * 作为测试 可以注释掉下面这一行 可以发现自定义处理器中session的username总是为空 + */ + return super.beforeHandshake(request, response, wsHandler, attributes); + } +} +``` + +#### 2.3 创建websocket的配置类 + +```java +/** + * @author : heibaiying + * @description :websocket 配置 + */ +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(new CustomHandler(), "/socket").addInterceptors(new CustomHandshakeInterceptor()); + } +} +``` + +#### 2.4 前端 websocket 的实现 + +```jsp +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + ${sessionScope.get("username")}您好!欢迎进入群聊大厅! + + + + +
+ +
+ + + + +``` + +#### 2.5 简单登录的实现 + +```java +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Title + + +
+ + +
+ + +``` + +```java +@Controller +public class LoginController { + + @PostMapping("login") + public String login(String username, HttpSession session){ + session.setAttribute(Constant.USER_NAME,username); + return "chat"; + } +} +``` + diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/constant/Constant.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/constant/Constant.java index a3417e6..70ef5a5 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/constant/Constant.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/constant/Constant.java @@ -1,9 +1,7 @@ package com.heibaiying.constant; /** - * @author : 罗祥 - * @description : - * @date :create in 2018/12/27 + * @author : heibaiying */ public interface Constant { diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/controller/LoginController.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/controller/LoginController.java index f7c2276..f3e5541 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/controller/LoginController.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/controller/LoginController.java @@ -8,9 +8,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; /** - * @author : 罗祥 + * @author : heibaiying * @description : 简单登录 - * @date :create in 2018/12/27 */ @Controller public class LoginController { diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/DispatcherServletInitializer.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/DispatcherServletInitializer.java index 000b86f..f0360a6 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/DispatcherServletInitializer.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/DispatcherServletInitializer.java @@ -3,9 +3,8 @@ package com.heibaiying.webconfig; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** - * @author : 罗祥 + * @author : heibaiying * @description : 等价于 web.xml 中配置前端控制器 - * @date :create in 2018/12/27 */ public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/ServletConfig.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/ServletConfig.java index af45804..8f967d3 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/ServletConfig.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/ServletConfig.java @@ -10,9 +10,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** - * @author : 罗祥 + * @author : heibaiying * @description : 主配置类 - * @date :create in 2018/12/27 */ @Configuration @EnableWebMvc diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/characterEncodingFilter.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/characterEncodingFilter.java index 0958a33..ddcce72 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/characterEncodingFilter.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/webconfig/characterEncodingFilter.java @@ -6,9 +6,8 @@ import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; /** - * @author : 罗祥 + * @author : heibaiying * @description : 编码过滤器 防止乱码 - * @date :create in 2018/12/27 */ @WebFilter(filterName = "characterEncodingFilter", urlPatterns = "/*", initParams = { diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomerHandler.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomHandler.java similarity index 97% rename from spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomerHandler.java rename to spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomHandler.java index 5e41ab8..c842878 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomerHandler.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/CustomHandler.java @@ -15,7 +15,7 @@ import java.util.concurrent.ConcurrentHashMap; * @author : heibaiying * @description : 自定义消息处理类 */ -public class CustomerHandler extends TextWebSocketHandler { +public class CustomHandler extends TextWebSocketHandler { private Map nameAndSession = new ConcurrentHashMap<>(); diff --git a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/WebSocketConfig.java b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/WebSocketConfig.java index 7854d56..46cb88d 100644 --- a/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/WebSocketConfig.java +++ b/spring/spring-websocket-annotation/src/main/java/com/heibaiying/websocket/WebSocketConfig.java @@ -6,9 +6,8 @@ import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; /** - * @author : 罗祥 + * @author : heibaiying * @description :websocket 配置 - * @date :create in 2018/12/27 */ @Configuration @EnableWebSocket @@ -16,6 +15,6 @@ public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(new CustomerHandler(), "/socket").addInterceptors(new CustomHandshakeInterceptor()); + registry.addHandler(new CustomHandler(), "/socket").addInterceptors(new CustomHandshakeInterceptor()); } } diff --git a/spring/spring-websocket/README.md b/spring/spring-websocket/README.md new file mode 100644 index 0000000..8f82b01 --- /dev/null +++ b/spring/spring-websocket/README.md @@ -0,0 +1,233 @@ +# spring websocket(xml配置方式) + +## 一、说明 + +### 1.1 项目结构说明 + +1. 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候用临时用户名作为session的id; +2. CustomHander为消息的自定义处理器; +3. CustomHandershakerInterceptor为自定义的 websocket 的握手拦截器; +4. 项目以web的方式构建。 + +![spring-scheduling](D:\spring-samples-for-all\pictures\spring-websocket.png) + + + +### 1.2 依赖说明 + +除了基本的spring 依赖外,还需要导入webSocket的依赖包 + +```xml + + + org.springframework + spring-websocket + 5.1.3.RELEASE + +``` + + + +## 二、spring websocket + +#### 2.1 创建消息处理类,继承自TextWebSocketHandler + +```java +/** + * @author : heibaiying + * @description : 自定义消息处理类 + */ +public class CustomHandler extends TextWebSocketHandler { + + private Map nameAndSession = new ConcurrentHashMap<>(); + + // 建立连接时候触发 + @Override + public void afterConnectionEstablished(WebSocketSession session) { + String username = getNameFromSession(session); + nameAndSession.putIfAbsent(username, session); + } + + + // 关闭连接时候触发 + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { + String username = getNameFromSession(session); + nameAndSession.remove(username); + } + + // 处理消息 + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 防止中文乱码 + String msg = URLDecoder.decode(message.getPayload(), "utf-8"); + String username = getNameFromSession(session); + // 简单模拟群发消息 + TextMessage reply = new TextMessage(username + " : " + msg); + nameAndSession.forEach((s, webSocketSession) + -> { + try { + webSocketSession.sendMessage(reply); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + + private String getNameFromSession(WebSocketSession session) { + Map attributes = session.getAttributes(); + return (String) attributes.get(Constant.USER_NAME); + } +} + +``` + +#### 2.2 创建websocket 握手拦截器(如果没有权限拦截等需求,这一步不是必须的) + +```java +/** + * @author : heibaiying + * @description : 可以按照需求实现权限拦截等功能 + */ +public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { + InetSocketAddress remoteAddress = request.getRemoteAddress(); + InetAddress address = remoteAddress.getAddress(); + System.out.println(address); + /* + * 最后需要要显示调用父类方法,父类的beforeHandshake方法 + * 把ServerHttpRequest 中session中对应的值拷贝到WebSocketSession中。 + * 如果我们没有实现这个方法,我们在最后的handler处理中 是拿不到 session中的值 + * 作为测试 可以注释掉下面这一行 可以发现自定义处理器中session的username总是为空 + */ + return super.beforeHandshake(request, response, wsHandler, attributes); + } +} +``` + +#### 2.3 配置websocket + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +#### 2.4 前端 websocket 的实现 + +```jsp +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + ${sessionScope.get("username")}您好!欢迎进入群聊大厅! + + + + +
+ +
+ + + + +``` + +#### 2.5 简单登录的实现 + +```java +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Title + + +
+ + +
+ + +``` + +```java +@Controller +public class LoginController { + + @PostMapping("login") + public String login(String username, HttpSession session){ + session.setAttribute(Constant.USER_NAME,username); + return "chat"; + } +} +``` + diff --git a/spring/spring-websocket/src/main/java/com/heibaiying/constant/Constant.java b/spring/spring-websocket/src/main/java/com/heibaiying/constant/Constant.java index a3417e6..50fcc31 100644 --- a/spring/spring-websocket/src/main/java/com/heibaiying/constant/Constant.java +++ b/spring/spring-websocket/src/main/java/com/heibaiying/constant/Constant.java @@ -1,10 +1,5 @@ package com.heibaiying.constant; -/** - * @author : 罗祥 - * @description : - * @date :create in 2018/12/27 - */ public interface Constant { String USER_NAME="username"; diff --git a/spring/spring-websocket/src/main/java/com/heibaiying/controller/LoginController.java b/spring/spring-websocket/src/main/java/com/heibaiying/controller/LoginController.java index f7c2276..c51a7f3 100644 --- a/spring/spring-websocket/src/main/java/com/heibaiying/controller/LoginController.java +++ b/spring/spring-websocket/src/main/java/com/heibaiying/controller/LoginController.java @@ -3,12 +3,10 @@ package com.heibaiying.controller; import com.heibaiying.constant.Constant; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; /** - * @author : 罗祥 * @description : 简单登录 * @date :create in 2018/12/27 */ diff --git a/spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomerHandler.java b/spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomHandler.java similarity index 94% rename from spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomerHandler.java rename to spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomHandler.java index 6ee4e2e..9a78700 100644 --- a/spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomerHandler.java +++ b/spring/spring-websocket/src/main/java/com/heibaiying/websocket/CustomHandler.java @@ -3,7 +3,6 @@ package com.heibaiying.websocket; import com.heibaiying.constant.Constant; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; @@ -16,7 +15,7 @@ import java.util.concurrent.ConcurrentHashMap; * @author : heibaiying * @description : 自定义消息处理类 */ -public class CustomerHandler extends TextWebSocketHandler { +public class CustomHandler extends TextWebSocketHandler { private Map nameAndSession = new ConcurrentHashMap<>(); diff --git a/spring/spring-websocket/src/main/resources/springApplication.xml b/spring/spring-websocket/src/main/resources/springApplication.xml index 80023cc..5f4febe 100644 --- a/spring/spring-websocket/src/main/resources/springApplication.xml +++ b/spring/spring-websocket/src/main/resources/springApplication.xml @@ -32,10 +32,10 @@
- + - +

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 literal 0 HcmV?d00001 diff --git a/pictures/spring-dubbo.png b/pictures/spring-dubbo.png new file mode 100644 index 0000000000000000000000000000000000000000..83a4a7583e0f211f252f7d95e42b6682c338a195 GIT binary patch literal 9366 zcmdUVWmH_vwrwN92^t`{69^KV;L^BzfX0GLn#O`Qjk^Sb1P^Y(0t6Z-SbzY*t#Nk= zZn>TBym8OCcf9ldzaP7L@2cJdfr)wi%~-{?9|^a6X4T2&2A**aw84ree+-H6B-@tGjwE368{R zy|Ch1kyr7zbY@{13?K0U0ld^>y4BurF`DtzB#M%wo>W=Q8qI^r41qQYLQ5@{Xs6rn zC~WGe?!={5myfkAXDah424Bs-Y~H1h;Vs!+`Q(@u=H_l2`M|y>GAZ`B!0r~VPr3j* zV2g6QLUMW^SlQTIFAt2+Lu6Y2Jl+8U{f^tng);Fg3@X2ydMyeb3eC^Y|3V|ub&HJOXWxnw|k0`7DnqgNQDt{@tZXNeO z3i;`WeQ{JfySrTtPBS&$r*GBN)PRE+7#Oek_=4x>jeq7!Nx4Apuh$ds;}BKm9q|(- znpWN6_}VBp)0HNlva)*0bW3W$i=v!wYAoiVI;dlJ=jR31OOv^EVuxb~8Z?`Ce(SW@KdnH8lw&Z+DoS=j*YD(s&a5?Hj?1(W+_O zdDYbf9oM})HJw>`;_YET_u#-*f~(RXh<*uH9M?G3c!Tw`p@| z?&En$lh1EkYd=Lr%;=aH*Y!SpKxeUfrjFxs=|ZE6m4yXhf4WljW;XTW zyuZMFpt6s@ohVBRM$6Q0M>yY(-`}T0#riU|2wx=N(R;o?NSnI5w({jFty(pd5#W8? zb_F?{7o41&w75CjblpVuTTxvdzpuZa2n&7Ov7o#h2RVQz08Z0pQhj}W_8H6b@bBUH zRIgx<{>Tn9Iiid5@&-`}gDoEKZ)R&Oo-dX+6cD_1Pf$nIWj^-T{oQx*5(8 z#Le|T!v;tbqJIIwi2;zud!NYsNKMHbW+!3RCGU0o*tj^9$egbnN!fPuPT*+dFDHC;>A$90&4Sp*66Z4 zZR%|ZQ_^iK`+R`{+bv2P-(kU1kFZ)WfxEFF2a@<>l!=K6xg2BtA5+}*H8W8P1>a#5 zYOnY7p!fCljT?ukiZwm#C`zFM#P1I3b`6N+sl~#(tE>7jmWcsrD1d74asO%}QImcb z$9XKlb_%`Vj)H>&?$d;WUP@2XHF{$e0;_Zv^zAg9M2lTBq2M;B@U=Y@K<#RW<(v?v zLSxCdqpO{Qgtgm?{U*q&to1_lvzI5x42^x?4>x6spaJXKBWu>9>AkY@^6!dt(9qgi zUQVO0%#{xO08(=D_1b<~IT#FP++RY2s1MGtL9tLSOXc?-(~c%bQQCJI&(_#HI$w_{ z(xw1dl$uj&OTex7P6U^G`73C4=;mVt_tFovq|ADs)9W-^U+mZbC@<8yk&|6xGekx$ z;Y$j;oya}eZKgI|cA4cO+`5+o_@2zs-7&m`TfgLI@FR$EzF^)jQ znlys*3JTCjNJ#z}5Kj3$9}fpd@X+RW1l*mepM7GhyW)Wo>e`Ax#yGFt2(|dl#z*gqDZ^7FrdW++y-s%t z#R(p^?e6RZC@3m2?SpG|C&$LLL2$PxPBT^NWnj-=%}4~W9#*G$6N@2J;N`%^#-XG;FWu4tvcTwW0wmR0-qbywxZwd(?)>^K)N}%CM6M{UtYfT@DQl-_wXQXYioPK&fbMAv1l^$v}l3e37Nqj zJVCAAMAaRSqTuEBO1L>A(yrl`VxD_?8&##ZpYrn=k-$nfQ*GXlgipL2d2o@S+t4{a zIum*xv7h48f}+WwltlQ}x`;Sq+(^$X6gp~=SwQ+SMS?)p$xGTf-9uNF5dD54e9D`* zmkI~ySZ6odheWww6B8jbW`6iFFb%)~pk%b>zx;-+&DvcdD7o;gW8n3b~YAm{f>w`@g*soVu z^_pEDTg8?a={a89+!s86R?})DkEDBhdvA_pr+J%*650Qq3}XaBMDPHK{R|{T&zk1| zHNF>n{#PN9FRTLY7M9(NRe)PPD+<8ke<#ToE0;0mZO^WJdAxZShFMoaR0-*^xUb#j z%2fmD^*&2DTWmwbIM7jK<;4WNG!4LH>mec=lA$tk>619>go{UDbbhmA5ex$O*!Xzx z(NDuF87S?XC>uV;5|z)*!nhRZ5tmi+4)0IH&(wr1KU-n55Us${_|JnG-x5P4^uNAwo2CIwQ*d>GVyy$k|K*G|VUzZIn}&x>!y3S_P{;XIBK8s|yX>o3Zc^&Y?XuSKtnh`s z8n10*kQkBF;tL~foLEpGyIq_B7yoJ-k+2&sMhI4ztgGgYvy+qD3sO|TU!3uhKrgh= zS}Zd^a*=H?f3QNEcM2aXb;hdCpQ`r!Y)nq6mvWtX**!Chg6R)2$|Pjp{i5JG{uT=B&n;(YjPA8U%*P*lx zGII@p5t5=^(0tk@Cn5sD5A-#DsqWK114hxv>U@0z_tRzizH`=@&vAgj^Pr>XH};}& z9@HywWWc~EWM;vgIqHf3(aIJHZq%!O!41@(l08pIwwQ@m*@>g6zr%Kr*p`;6>b=lD z>Q2>(&H6AnlrtM6>QS(nGAqdXG4POqKBM^|e!# zUziu?zC#K)d@QU#uf_V?L%C6= zvI9IW!pGh)k>3T~eu%Wh1zew~RthoRg^rn7%72s!w4i{14ibYy7ejtQm^gpoQ1kjb zP#3Td`0S=Eyj?IH6dRjwr;6{JB!0E`Qf71Btw}Msv~J*dLvU7H=&ul6JMd<^N zZe#8`1vR=*%i?&1cvXVon3PtuDOgw~c+uXc=tW4Gv6YTkx-j{wzpz&8iT%u0wY%!xv6FoXC6P9waC$ESn*=Kg-^ou~oUr~!%+b_{Nd7DkEnru9)nB7Pya?ej$W3(Gq3=Gv5eHBjl^ge+%| zAV_yA?Z7|fF_)yua>XKM(soD&4@83GrryB;j#;{#H_grl)q8AhTgDfxEv%wv*Gm9m zgw~I#$l=*Iv>VpI(I!&<=Lve2q{dY)bzG2QmtH&VM3(OV61_BVC#(Fb4=2(Kx!FX2ntd?;ADq2WN zjeaViCU4|WA^ScB{c1|SbnuQwzev+~;q5K9!);i(>1<0QkT%W+wy6YaGO$y5lkYCk zFf#DshCGEe&bNP}jr9iV!hD}&;_l8*3q2qEk}xZD^~dP{i+tvd}Aa88wlK> zbVki5lc&}jIqq3v297xTcuYr2C&_5t^YZHI#NclRk`^`$G9_iFX~4zDvmMO?J$A>N zxVykjnxIU|N_+o~9|lH(4c_9CkzMqFS1>b5(C4ZzIRCuk73zcE?Z9)<<)%lpF7OS8M$&%z2hg$d z1uXSG#!;RF#fEZ*IrliO(EQ23%`h6%0d1%#wX_Ju&7AI1D62yrc8(Th%$6@_9K|ID zQ_$4WT*z&eBXg@1kykAFh3S+V02P2K+N$9(xT)cS_06E7oVssBwGk2YbPN~xM7?A+ z6MNgtA&Bpkki4pw+bjDhUmW0bddTln@I70~Av=LoT!~aTo1IGelKU5R#QJEMkQy5Rpr+;vUd*|Z^5E=^!WG>I@(Gg5 z2`s8TgvqZ%$-q>U3;ZV!nVj=eYU>#rr)><>uib$Ddu1iX+VXEZuBS|}hlHWOS9i2C z1_#P{SgOPk@i$~LRXCnjBIAMQ)b@C&37!uvnK+so?kv{Pfs<_>5uxupKc|Q)a-H_=y9d#0KeTLg?A-cl91-3EON-Osdj4 zS+oNuhPo~4tGES#w`+>Ja`JlP*-hq_Z9;w&L)pM zJz;jIJSju8naD?)f&uL67qX=C-q`?p7JFr5+L?Bpr6_|oqBytM30!SSg#!ph^^keI zL_QYpMq&=}!Bqj`r7Wr3i4ql|r+MGbWB5WE@rfD@56cR}U}_ddBa$5W-|m*w7+3m0 zzaRh9T*=S%=zIP<3(`Gck=*_wK_o%kOORqK^Z+E#E*$4RljpsRYi0ou|b@1erxeWp!T1v zA(lPBO_9Bs~Bxi(m@<;8cj8-dfsZQLa+ovbFr=afwJIwa*e>wK($%Vv0T~=Ln=7MwcB`LzmJtjI2<%xcDUcgZ-IUFH`Zzp|xOb>2j^4cCpcA9L016NiY9zJn6zXEESNun9Lwk9}Lc8nlL(B~n?7 zn=Mc#37xlglk7&f`q4s>P2csi-1F?HZf&~jk(`|Y+q34R#04GNiX)d`eF;Og_xL)6 zv^%bY3stU<#X4srQS+CxWjOc45|`_SdX9+PeM!Arz z@x(ZAMy-I0H89T~`Oar);vTgrqs0xw2a1Vej)CY;g*1wl=dItAXwg`5Wuf?AT=Cgj zY}EjA{J8(BwBTKN(ic58C&hu>UsEx!0Op!(0I@wM0b0$RgA862yx~`BglL}$iF+u( zx+&HyK4ND+cOgxYuYyrZi3fnH?}tAD!fi9MB%U#+VZV({lJq8H)*xIDWKj;LQ2o~o zB%_^F%qOVty^S*eNx)X68fz2b5%vw`UdH|pAfSGS-qSy##$cS^t;{SOo4s=_7BrhRys~DKj-CWqR+p=b`{4@6~>&N=3bZ;qWz?rhjOD__ZzB-TZ{)jgTGj z%jlvN1I|eAy`{{*j|9+1{^50bS3Dk7m%_EUG&mh1^wpc`G-mnO~;E7y5mNvDl>dn*8+@o%|`}T&Lg`!W4Bf}rg zOBxI_Ec6YlA?*O)?0T2wiOzPqey&>{=$V~J{SEWeKO1~K48re2a}}1Cs!L4ih<0B# ztz51a5@K5qZEGwtQ?v=HF1;7~s-E7?omm0pxBQ*g_J-+)?sPSbT(epPb^NkrW8TN!6@hHj= z=RroUu0EDbkF>aU(81vH<`}55=!+ z5{*`aw<*es$I4_*s8yWx;_8shp?Tp-pyn8!YZ0rfp8w@VQ*|(NMgVtC0gf|C9pl7| zjk`y2kx1OvuQZ9dPoE?^>`@-z|Fy6}@?l6hC_|{2Dj^(Ub0)e#%-MzOeLJb(>}(X? zxpcnA#0dSX=mT5YAZ}#r=1UKc-!+*E>T?5Lk&}Z*6sGPwtQLc@0i7K%ozRbTBVB9x z%Kos`;ZjkcE1uNNhyrMyHqZ~hgH_gAD4?U`L;*aye3k3E(C$9U1!&CwCUFhN7Qco^ zQC~zy+GYfsxHB>G<*z7!)9JBPPd7$KHe0BG$@0|y%|(#v#rXL6zx0ax04YTzcxwC$ zL1B&OpdI4DFGH@5J2b;*_)hJq>$F5;YFfXT8r}0$uZN~i{k=jWZ9fO&gYle=R@`Mu z?G;6qALs`IgYm!<1kRTAhFFB?Q!n@ADz&+rRwl~3H&x9Vmuh97%nLF_5mc2*J}>(i zIf-1#DMo2l-5J&LX1i{_@{#%HXQ{$nlq98-oB6XS5zVg_2y44USql1fevNV!7$w}sDb zMQeFOUkos8H~uL&dukA~1x1AQZPQr3E^XbnVsv_3fFf7cBe(reZhY5C(ba_5r9%3B z!~|AMUwiXI6q19zgs71+_-2puN;Hh?32kV{kwPKZQ-QvYBVCN?N-_bXT)NAq?noXg z0?1XBz6hYB6r;}Ato4`3u9=D00BlHC)=^frSqca_hA|6@tzksOFP_X++P_=Ik9a4Q zu_E&W#hzD1IyuQJAvx*B$y08FO8LiOlih5NnZ4kCH2T%lA5}bU zR-aZ8!b+sBD5Ige?7RCU_Q4hla1znD++)JiMmYC4t;(}9qbPozu;Rx)xzh8jMP>Nh4xtP^mDN{_03SJS4i!;f0i@)s5?!w58qMP`tM)_>5;nU zN1%a?X1*v_+;<#HbPp2kX9-Rx{mXc(f7|<8Kmhym8W4HgDC_c9`g1$q8T(EHhh9(# zUh`aWb&bP7B!-uCU01LCz^=5u@<4w1u0<`apE>;G6+%!p@Ey`PfphLLrvy&Z+j)jS z0bS(KVzR*;QvG1Id@(~LW2wqSvYaO^TMEErtpCYube4h_Qk;(02OF+_Pl*$ygO-9# zT>ey#E&SQ{7t{o@rd_NQ)8;)qhSXg@VA`!;zW&{qDT2J_j#T2WS5yQ$WG3l4RBwnq z=w?!}cOPpdv{ALDR z)PVd;X?uA)q@nI;q@0AyB7^;{;mioF7oqL# z?Vt%ssB(*XC@||xWR!WR4*5}><{eGleN{!bk^iAdTXh2KGg?~LDiRXuiZbgG;{ym ztx=9kMn$NFR0!m`Eg?>rMT7Aef*KZ4M?WWlCBG>dskvvegKfO1ve_DOK0wkiLw6uX=K7G9`XicE zQzP!9$DXoub^-%pDUh{;q`}wy`|dg0*xxZPVgkqno<^+H-VwEaIx8dG46}vQ%{lY) z)i|&^yJD9|(qD-=CoQwx)%GHP$CF)H2=+!e7 z)+UfhBtpNaZ=SFkA7>cAh(YA4OwJPJyN>V~={>ppbcTKGxA9rmEPxgBZ}$ZEn$_n! z$A3&7Y$q=p+Iaz;fmRNa?-}zwNIj5bGarb<-9SgA&G*;aIsC79`~UVhJYr*Yf%#|Z zq}^1kW9)%D9soe6`}-|GVsDOG#Mylvs<&DrQskNn|5Y<$_1Tu14kSz9c!Llb4E(|t zseP9gVF)x!neJt$t-P`}&dAx>=Q#PEq--CLn8bctd}sZE?(rldV<8vz=yP9vVUuBV z$|R1gLU837gD7BkY>xYyI{hA>PQfqiS(n6G_U{ecTwGbtl5;|>{>g9Amv<9>BQ#@p zNsZ{d$O9JPnZ)d% zen84Uwmu4#*onOjOT2H!aaFcCzsrYJMeV5}BuQqpIL?yj6|fcant@aU@iFgnX?o3f-i}WqcaYzM-kqj6lvG|Rt8W&_V5B2+Ivzu)(&*-0{P6Y?G z@8nb@icTH!yW$t|lwiMoe>fjz+VZ~0tEK=g{{`a)_Ge=W<0M7;eve|EGFF`^r8m_Y zYoB77O_Znm(cksQ_E0xWM1qaC>C#FSN_c#?9ZNN)+SNdE6CWnfc`=_-cLt$h=6|c? zV3)lxjAp8~=8Wqml;_FHo+?}B9hQHaw##ZVpnvxKAE$g?Oig`IvzS|dMoKcYGda*B zD1iT3ov=XA?QZHvt~Tt%yui#A8Q4U|Sf61sa(6`$9Qq!g>k*d~>Qo=`Iw1QbJf{j; zu&i%nRe6o{X#~Hl<7iCbg$-Qrb_~xv7pV-bgbeE|s`C-S6w&mi@M7iP74*nYFaUfx z^sMhEF#yY)55(<8w?#de#+0r<4NzoC|EHYsA9arZzYB`~5b$GV WQpddF(?xz$1W=aO09MIb1pgN;VXIpJ literal 0 HcmV?d00001 diff --git a/pictures/spring-email-annotation.png b/pictures/spring-email-annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc7e4f43b152be370835b917973d8ae01a74b69 GIT binary patch literal 15034 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 Vp!1dsxc?EPAge4>E@c$-e*k7YvSR=M literal 0 HcmV?d00001 diff --git a/pictures/spring-memcached.png b/pictures/spring-memcached.png new file mode 100644 index 0000000000000000000000000000000000000000..667fae2031bb654dd704b7f68bef24fa2a43495d GIT binary patch literal 16218 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 literal 0 HcmV?d00001 diff --git a/pictures/spring-mongodb-annotation.png b/pictures/spring-mongodb-annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..7394c90d7efe3c3191ffd7df039d9d3cc560e931 GIT binary patch literal 15583 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 W&SbNg$OgQe43d#h5HAzc_y1pU9yosh literal 0 HcmV?d00001 diff --git a/pictures/spring-mongodb.png b/pictures/spring-mongodb.png new file mode 100644 index 0000000000000000000000000000000000000000..57012a9103f4d7fb3db421593b8d3d7e19b9ca08 GIT binary patch literal 14536 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 Z+nzgcaT=Ej@D?KIwX_nXT+%q`{{ijJ8ma&Q literal 0 HcmV?d00001 diff --git a/pictures/spring-rabbitmq-annotation.png b/pictures/spring-rabbitmq-annotation.png new file mode 100644 index 0000000000000000000000000000000000000000..0e87d7e44b719df83ec46db638bb35388ef0ffa4 GIT binary patch literal 19520 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