參考:?一篇文章學(xué)會spring boot(包括jms和hessian的集成)
一、配置文件加載類?
雖然說spring boot原則上是建議去掉xml配置文件愉烙,但是對于一個(gè)已經(jīng)成型并上線運(yùn)行著的項(xiàng)目而言桅打,不論是代碼還是配置都是非常龐大而且復(fù)雜的是嗜。?
這些配置文件不只是spring的、struts2的油额,還有spring和mq集成的叠纷,還有spring和hessian集成的等等。?
僅涉及到spring和struts2的配置文件比較好改潦嘶,而spring和mq以及hessian集成的就稍微有些麻煩涩嚣。?
如若是mq集成和hessian集成的部分先還是以配置文件的方式不變,等簡單易改的部分搞定后再說掂僵,于是便需要知道在沒有了web.xml文件的spring boot項(xiàng)目中航厚,如何引入加載xml文件。?
經(jīng)了解之后發(fā)現(xiàn)其實(shí)還是很簡單的锰蓬,只需要自己再寫一個(gè)空的java類幔睬,然后使用兩個(gè)注解就好:
@Configuration
@ImportResource(value="classpath:spring.xml")
public class ConfigClass {}
@Configuration是向spring聲明這是個(gè)配置類,@ImportResource則是指明需要引入的配置文件路徑芹扭。
二麻顶、使用注解給屬性賦值?
在過去的項(xiàng)目中,有一些數(shù)據(jù)存放在properties文件中舱卡,然后在spring的xml文件中引用辅肾,從而給特定的對象的屬性賦值。?
而如果整個(gè)項(xiàng)目改成spring boot轮锥,就需要盡可能去掉能去掉的xml配置文件矫钓,就沒有了這種注入賦值,所以還需要知道怎樣在spring boot中達(dá)到xml文件配置一樣的賦值效果舍杜。?
只需要在對應(yīng)的屬性上使用@Value注解(注意:必須是注冊到springBoot容器里的新娜,且由容器來生成bean才能注入,不注冊的話spring才不管你死活既绩,嘿嘿):
public class User{
????????@Value("${tuser.name}")
? ? ? ?privateString name;
}
當(dāng)然了概龄,這種寫法的前提是在properties文件中有相應(yīng)的屬性配置,例如:
tuser.name=testtttttt
tuser.age=123
并且spring boot項(xiàng)目啟動后能夠加載到這個(gè)properties文件饲握,spring boot默認(rèn)會加載resources目錄下的application.properties文件旁钧,如果我們這些配置不在這個(gè)文件中吸重,還需要進(jìn)行其他的配置,例如在application.properties文件中使用spring.profiles.active進(jìn)行指定歪今,也可使用spring.profiles.include嚎幸。
四、使用注解給對象賦值:?
雖然說在java中有一切皆對象的說法寄猩,屬性和屬性所屬對象都統(tǒng)稱對象嫉晶,但是這里為了區(qū)分,我只能在上邊更精確的說到屬性田篇。?
而上邊那種賦值方式有個(gè)很明顯的缺陷替废,就是每個(gè)屬性都需要使用@Value注解,如果這個(gè)類恰好很大泊柬,有幾十個(gè)屬性椎镣,那么這種賦值將是一個(gè)很讓人煩躁的工作。?
而spring boot中也正好提供了一個(gè)更加方便的方式兽赁,只需要一個(gè)注解状答,就可以引用配置文件中的內(nèi)容給整個(gè)對象賦值。?
例如配置文件中有如下內(nèi)容:
mytest:
????user:? ?
????????name: test? ?
????????age:22
? ? ? ? ? phone:13533559797
上邊這種寫法是yaml文件的寫法刀崖,也就是在spring boot中默認(rèn)識別properties類型的配置文件和yaml的配置文件惊科。?
上邊的寫法實(shí)際上等同于properties文件中如下的寫法:
mytest.user.name=test
mytest.user.age=22
mytest.user.phone=13533559797
而我們要把這樣一些配置直接賦值給特定對象的方式,就是使用@ConfigurationProperties注解:
@ConfigurationProperties(prefix ="mytest.user")
publicclassUser {
????// @Value("${test.user.name}")
????privateString name;
????// @Value("${age}")
????privateintage;
????// @Value("${phone}")
????privateString phone;
}
類上邊的那個(gè)注解等同于下邊被注釋掉的三個(gè)注解亮钦,當(dāng)然了馆截,不論哪種方式,實(shí)現(xiàn)的前提都是這個(gè)user類能夠被spring 掃描到蜂莉,也就是說能夠被spring所管理蜡娶。
五、filter過濾器?
在原本的spring web項(xiàng)目中映穗,web.xml文件是必不可少的窖张,啟動tomcat后就會來加載這個(gè)文件。?
通常我們都會在這個(gè)文件中配置一些servlet以及過濾器男公,例如字符集過濾器,而spring boot不再使用web.xml合陵,就需要我們能夠用其他方式解決原本web.xml中的過濾器的問題枢赔。?
這里寫一個(gè)過濾器也很簡單,要實(shí)現(xiàn)javax.servlet.Filter接口拥知,并借助幾個(gè)注解踏拜,只不過這個(gè)功能應(yīng)該是java自己的,而不是spring boot新提供的:
@WebFilter(filterName ="myFilter", urlPatterns ="/*")
public class MyFilter implements Filter{
????@Override
????public void init(FilterConfig filterConfig)throwsServletException {? ? ? ? ????????System.out.println("進(jìn)入filter");? ?
????}
????@Override
????public void doFilter(ServletRequest request, ServletResponse response, FilterChain ????????chain)throwsIOException, ServletException {?
????? ? ? chain.doFilter(request, response);? ?
????}
????@Override
????public void destroy() {? ? ? ? System.out.println("走出filter");? ? }
}
六低剔、listener監(jiān)聽器?
說到了過濾器速梗,接下來自然要說的就是監(jiān)聽器肮塞,在java web項(xiàng)目中,過濾器和監(jiān)聽器都用的很多姻锁,也都常常在web.xml文件中有相應(yīng)的配置枕赵。?
在spring boot中寫一個(gè)監(jiān)聽器就更加簡單,比如就僅僅是下邊的幾行代碼就夠了:
@WebListener
public class MyListener implements ServletContextListener{ ???
?????@Override
????public void contextInitialized(ServletContextEvent sce) {? ? ? ? ????????System.out.println("contextlistener init");? ?
????}
????@Override
????public void contextDestroyed(ServletContextEvent sce) {? ? ? ? ????????System.out.println("contextlistener destroy");?
? }
}
同樣的位隶,上邊的類所實(shí)現(xiàn)的接口以及相應(yīng)的注解也都不是spring boot的拷窜,而是javax.servlet的。?
上邊例子中我們寫的是一個(gè)contextListener涧黄,同樣的也可以寫一個(gè)requestListener以及其他的listener篮昧,例如:
@WebListener
public class MyListener1 implements ServletRequestListener{
????@Override
????public void requestDestroyed(ServletRequestEvent sre) {? ? ? ? ????????System.out.println("requestlistener destroy");? ?
????}
????@Override
????public void requestInitialized(ServletRequestEvent sre) {? ? ? ? ????????System.out.println("requestlistener init");? ?
????}
}
七、ERROR錯(cuò)誤頁面?
在web.xml中除了配置了filter和listener外笋妥,比較常見的就還有配置error錯(cuò)誤頁面懊昨,我們項(xiàng)目中也同樣這么做了,因此在拋棄web.xml的時(shí)候春宣,也必然要考慮error頁面的問題酵颁,那么在spring boot中也同樣是非常的簡單,比如寫這樣一個(gè)類:
@Component
public class Test{
????@Bean
????public EmbeddedServletContainerCustomizer containerCustomizer() {
????????return new EmbeddedServletContainerCustomizer() {
????????????@Override
????????????public void customize(ConfigurableEmbeddedServletContainer container) {? ????????????????ErrorPage error404Page = new ErrorPage( ????????????????????????????HttpStatus.NOT_FOUND,"/404.html");? ?
????????????????ErrorPage error500Page = new ErrorPage( ????????????????????????????HttpStatus.INTERNAL_SERVER_ERROR,"/500.html");? ????????????????container.addErrorPages(error404Page, error500Page);? ? ? ? ?
????????????? }
? ? ? ? };
? ? }
}
需要注意的是信认,我這種寫法是jdk1.6可用的材义,還有一種寫法需要jdk1.7以上版本才行,這里就不舉例了嫁赏。?
并且我這里是寫了一個(gè)新的類其掂,我們也可以直接把具體的方法寫到啟動類那里,效果是一樣的潦蝇,只要都能被spring 掃描到款熬。
八、定時(shí)任務(wù)?
原本項(xiàng)目中使用了quartz定時(shí)任務(wù)攘乒,使用了大量的xml配置文件贤牛,這里就使用schedule替代。?
不過则酝,這一條雖然列在了這里殉簸,但是實(shí)際上我覺得可以不用列出來,因?yàn)檫@里使用schedule代替quartz沽讹,實(shí)際上也是spring原本就有的般卑,并不是有了spring boot之后才出現(xiàn),具體的我也曾寫過相應(yīng)的博客爽雄,例如:?spring schedule定時(shí)任務(wù)
只不過蝠检,在spring boot中更加的簡單,不需要我們再做任何的動作挚瘟,只需要這個(gè)簡單的類和注解就ok了:
@Component
@EnableScheduling
public class MySchedule{
????@Scheduled(cron ="*/2 * * * * ?")
????public void sTest() {? ? ? ?
????????System.out.println(Calendar.getInstance().getTime());?
? }
}
九叹谁、返回頁面?
返回頁面饲梭,在spring boot中叫引用模板,需要特定的依賴焰檩,例如:
org.springframework.bootspring-boot-starter-thymeleaf
當(dāng)然了憔涉,這只是其中一種。?
引入了相應(yīng)的依賴后锅尘,我們在spring boot項(xiàng)目的resources目錄下的templates目錄下建立具體的html頁面监氢,然后具體的controller中只需要返回相應(yīng)的html的文件名,即能成功返回頁面藤违。?
例如templates下有index.html文件浪腐,在controller中就可以寫成這樣:
@RequestMapping("/index")
? public String index(ModelMap map) {? ?
? ? ????map.put("name","testfsdfdsfdsfsdf");
????????return"index";
}
不過這里我覺得應(yīng)該也可以使用modelandview,但并沒有嘗試顿乒,不知是否可行议街,而且即便可行,在性能上如何也還未曾測試璧榄。
十特漩、spring boot 集成activemq,即jms?
前文中我有說到我們原本的項(xiàng)目中使用了spring 整合activemq骨杂,那么改為spring boot后不可能就把a(bǔ)ctivemq扔掉涂身,還需要找到可行的集成方案,可喜的是搓蚪,spring boot中有jms專門集成activemq蛤售。?
要實(shí)現(xiàn)這種集成,我們首先還需要導(dǎo)入jms相應(yīng)的依賴
org.springframework.bootspring-boot-starter-activemq
使用activemq發(fā)送消息需要有消息隊(duì)列妒潭,因此接下來就需要我們生成一個(gè)消息隊(duì)列的配置類悴能,用來指定queue:
@Configuration
@EnableJms
public class ActiveMQConfig{
????@Bean// 配置一個(gè)消息隊(duì)列
????public Queue queue() {
????????return new ActiveMQQueue("sample.queue");? ?
????}
}
有了隊(duì)列以后,然后就是發(fā)送消息:
@Service
public class MQProduceService{
????@Autowired
????private JmsMessagingTemplate jmsMessagingTemplate;
????@Autowired
????private Queue queue;
????public void send(String msg) {// 向指定隊(duì)列中發(fā)送消息? ?
????this.jmsMessagingTemplate.convertAndSend(this.queue, msg);? ?
????}
}
就這樣簡單兩步雳灾,我們的activemq消息服務(wù)器就算是寫好了漠酿,如果再其他地方調(diào)用這個(gè)service中對應(yīng)的方法,就可以實(shí)現(xiàn)消息的發(fā)送谎亩。?
有了發(fā)送端炒嘲,還需要有接受端,或者說消費(fèi)端匈庭。也是需要先配置隊(duì)列夫凸,因?yàn)槲疫@里都寫在一個(gè)項(xiàng)目中,所以就公用同一個(gè)配置就好嚎花,具體的消費(fèi)端代碼如下:
@Service
?public class MQConsumerService {
????privateString text;? ?
????@JmsListener(destination ="sample.queue")// 監(jiān)聽指定消息隊(duì)列????
????public void receiveQueue(String text) {
????????this.text = text;? ? ? ?
????????System.out.println(text);? ?
????}
????public String receive() {
????????returntext;? ?
????}
}
不論是發(fā)送端還是消費(fèi)端寸痢,代碼都很簡單呀洲,為了更直觀的看到結(jié)果紊选,我編寫了一個(gè)controller來調(diào)用相應(yīng)的服務(wù)實(shí)現(xiàn)發(fā)送和接受啼止,代碼如下:
@RestController
public class MQController{
????@Autowired
????private MQProduceService produceService;
????@Autowired
????private MQConsumerService consumerService;
????@RequestMapping("/send")
????public String send() {? ? ? ?
????????produceService.send("this is an activemq message");
????????return"send";? ?
????}
????@RequestMapping("/receive")
????public String receive() {? ? ? ?
????String str = consumerService.receive();
????return str;? ?
????}
}
這個(gè)代碼非常的常規(guī),也就不做多的解釋了兵罢。
十一献烦、spring boot中使用hessian?
mq分為發(fā)送端和消費(fèi)端,而hessian作為一種webservice卖词,也是一樣具有服務(wù)端和消費(fèi)端巩那,不過與mq不同的是,hessian需要在web.xml進(jìn)行一定的配置此蜈。?
與之前hessian的實(shí)現(xiàn)方式一樣的是即横,服務(wù)端需要有相應(yīng)的接口類和實(shí)現(xiàn)類,例如:
public interface HelloWorld {
????public String hello();
????public Map helloMap();
}
@Service("helloWorld")
public class HelloWorldImpl implements HelloWorld{
????private static final long serialVersionUID =1L;
????@Override
????public String hello() {return"hello hessian";? ? }
????@Override
????public Map helloMap() {? ? ? ?
????????Map map =newHashMap();? ? ? ?
????????map.put("message","hello word!!!!!");
? ? ? ?return map;? ?
????}
}
而不同的是裆赵,之前使用web.xml時(shí)在web.xml中進(jìn)行了配置东囚,而在這里則是使用了一個(gè)類來暴露接口:
@Component
public class HService{
????@Autowired
????private HelloWorld helloWorld;
????@Bean(name ="/springBootDemo/HelloService")
????public HessianServiceExporter exportHelloService() {? ? ? ?
????????HessianServiceExporter exporter =newHessianServiceExporter();? ? ? ? ?
? ? ? ? ?exporter.setService(helloWorld);? ?
?????????exporter.setServiceInterface(HelloWorld.class);
????????return exporter;? ?
? ? ? ?}
}
就這樣,在不使用web.xml的情況下我們也一樣實(shí)現(xiàn)了spring boot和hessian服務(wù)端的集成战授,或者更準(zhǔn)確的說页藻,是spring和hessian服務(wù)端的集成。?