SpringBoot入門&Swagger

SpringBoot是基于spring框架衍生的一種新的微服務(wù)框架迂猴,如果對(duì)Spring有一定了解的同學(xué)肯定知道在Spring中需要配置各種xml文件完成bean的注冊(cè)操作线梗,隨著服務(wù)越來越多,配置就變得越來越復(fù)雜溪胶,而SpringBoot就可以比較好的解決這個(gè)痛點(diǎn)甚纲,又例如需要搭建一個(gè)Spring MVC的環(huán)境听盖,在maven中需要手動(dòng)加入各種依賴包绞吁,但是SpringBoot卻提供了spring-boot-starter-web可以幫我們解決開發(fā)一個(gè)Java Web項(xiàng)目的所有依賴情況

SpringBoot不是獨(dú)立于Spring存在的幢痘,SpringBoot就是把Spring的功能再次進(jìn)行包裝,對(duì)外暴露了更高層次的方法家破,使得我們?cè)谑褂玫臅r(shí)候可以省去很多配置和操作颜说,約定俗成優(yōu)于配置,接下來就來快速學(xué)習(xí)下SpringBoot 如何使用的以及一些其他特定的功能员舵,其中有些要稍微了解下Spring的知識(shí)脑沿,感興趣的可以看看【目錄】Spring 源碼學(xué)習(xí)

項(xiàng)目demo地址 simple-springboot

目錄

10分鐘入門SpringBoot
1、Demo
2马僻、展示所有的bean信息
3、HTTP請(qǐng)求 監(jiān)控輸出
4注服、Swagger

1韭邓、Demo

如下圖就是SpringBoot的文件目錄結(jié)構(gòu)


image

Bootstrap 文件

整個(gè)的SpringBoot啟動(dòng)入口措近,如下@SpringBootApplication就是SpringBoot的自動(dòng)配置相關(guān)注解,@ComponentScan則是包掃描的路徑女淑,其次包含了swagger的注解瞭郑,后面再介紹

@SpringBootApplication
@ComponentScan("com.demo")
@EnableSwagger2
public class Bootstrap {

    public static void main(String[] args) {
        SpringApplication.run(Bootstrap.class);
        // SpringBoot啟動(dòng)
    }
}

BeanIoc 文件

加上@Configuration就是SpringBoot的配置,里面包含的@Bean則是類似于Spring的xml文件配置的bean一致鸭你,只是從xml文件變成了類文件

// 這個(gè)參數(shù)設(shè)置的是beanIoc這個(gè)類本身bean的自定義beanName
@Configuration("beanI")
public class BeanIoc {

    @Bean
    public StudentService studentS1ervice() {
        // 在這里就是為了驗(yàn)證注入到spring IOC容器的名字到底是如何的屈张,所以故意加了一個(gè)1
        // 通過結(jié)束bean的刷新監(jiān)聽事件打印出的beanName可以具體驗(yàn)證該操作是否可行
        return new StudentService();
    }

    @Bean
    public CustomContextEventRefresh customContextEventRefresh() {
        return new CustomContextEventRefresh();
    }

    @Bean
    public PeoplePropertiesPrefix peoplePropertiesPrefix() {
        return new PeoplePropertiesPrefix();
    }

    @Bean("student")
    public StudentServiceWithCustomConstruct studentServiceWithCustomConstruct() {
        return new StudentServiceWithCustomConstruct("custom");
    }

    @Bean("SpringContextTool")
    public SpringApplicationContextAware springApplicationContextAware() {
        // 這個(gè)bean后續(xù)會(huì)重點(diǎn)關(guān)注下
        return new SpringApplicationContextAware();
    }

    @Bean("bean1")
    public Bean1 bean1() {
        return new Bean1();
    }
}

PeoplePropertiesPrefix 文件

和properties文件做映射處理,會(huì)自動(dòng)匹配符合的前綴

@ConfigurationProperties("people")
public class PeoplePropertiesPrefix {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

application.properties 文件

如上述的PeoplePropertiesPrefix的注解信息是people開頭袱巨,則會(huì)自動(dòng)和下面的people開頭的屬性進(jìn)行映射處理

people.name=zhangsan
people.age=18
people=hello

StudentController 文件

該文件中列舉了在HTTP請(qǐng)求中不同的參數(shù)提交方式阁谆,并且所有的方法都加上了@ResponseBody,則意味著直接以函數(shù)的返回值為HTTP請(qǐng)求的body數(shù)據(jù)填充愉老。

  • 無參數(shù)的GET請(qǐng)求方式
  • 帶?參數(shù)的GET請(qǐng)求方式
  • 帶路徑參數(shù)的GET請(qǐng)求方式
  • JSON參數(shù)的POST請(qǐng)求方式
  • Map參數(shù)的POST請(qǐng)求方式
  • 表單提交的POST請(qǐng)求方式

其次關(guān)于swagger以及獲取bean信息的相關(guān)點(diǎn)后面再介紹

@RequestMapping("/")
@Controller
public class StudentController {

    @Resource
    private StudentService studentService;

    @Resource
    private PeoplePropertiesPrefix peoplePropertiesPrefix;

    @Resource
    private SpringApplicationContextAware springApplicationContextAware;

    @Value("${people}")
    protected String people;

    @ApiOperation("基礎(chǔ)GET請(qǐng)求")
    @GetMapping("/index")
    @ResponseBody
    public String index() {
        // 非吵÷蹋基礎(chǔ)的get請(qǐng)求
        return "{\"name\":\"zhangsan\"}";
    }

    @ApiOperation("基礎(chǔ)POST請(qǐng)求")
    @PostMapping("/index.do")
    @ResponseBody
    public String indexPost(@RequestBody Student student) {
        // 使用json的方式去提交
        String name = student.getName();
        return "{\"name\":\"" + name + "\"}";
    }

    @ApiOperation("帶路徑參數(shù)的GET請(qǐng)求")
    @GetMapping("/index2/{id}")
    @ResponseBody
    public String indexGet(@PathVariable String id) {
        // get的方式,帶上了路徑參數(shù)
        return "{\"id\":\"" + id + "\"}";
    }

    @ApiOperation("帶上?參數(shù)的GET請(qǐng)求")
    @GetMapping("/index3/")
    @ResponseBody
    public String indexGetWithPar(@RequestParam String id, @RequestParam int age) {
        // get的方式,帶上get請(qǐng)求的參數(shù)
        Map<String, Object> map = new HashMap<>(2);
        map.put("id", id);
        map.put("age", age);

        return JSON.toJSONString(map);
    }

    @ApiOperation("Map參數(shù)的POST請(qǐng)求")
    @PostMapping("/indexPost")
    @ResponseBody
    public String indexPost2(@RequestBody Map map) {
        return "{\"id\":\"" + map.get("id") + "\"}";
    }

    @ApiOperation("Form參數(shù)的POST請(qǐng)求")
    @RequestMapping(value = "/indexPostForm", method = RequestMethod.POST)
    @ResponseBody
    public String indexPost3(Student student) {
        // 其實(shí)content-type是application/x-www-form-urlencoded
        String name = student.getName();
        return "{\"name\":\"" + name + "\"}";
    }

    @PostMapping("indexb1")
    @ResponseBody
    public String indexBean1(Student student) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("id", studentService.getName(student));
        map.put("age", studentService.getAge(student));

        return JSON.toJSONString(map);
    }


    @GetMapping("/indexp")
    @ResponseBody
    public String indexp() {
        // 非臣等耄基礎(chǔ)的get請(qǐng)求
        Map<String, Object> map = new HashMap<>(2);
        map.put("name", peoplePropertiesPrefix.getName());
        map.put("age", peoplePropertiesPrefix.getAge());
        map.put("all", people);

        return JSON.toJSONString(map);
    }

    @ApiOperation(value = "獲取Spring Bean信息", notes = "Spring Bean")
    @GetMapping("/indexbc")
    @ResponseBody
    public String indexBeanCount() {
        // 非逞娴粒基礎(chǔ)的get請(qǐng)求,獲取bean的信息
        // 后面再介紹這個(gè)請(qǐng)求
        List<String> list = new ArrayList<>();
        for(String beanName: springApplicationContextAware.getBeanName()){
            list.add(beanName + "\n");
        }
        return JSON.toJSONString(list);
    }


    @PostMapping("/get_request_info")
    @ResponseBody
    public String indexWithHeader(HttpServletRequest request, @RequestBody Map map) {
        Enumeration<String> headers = request.getHeaderNames();

        Map<String, Object> res = new HashMap<>(2);
        res.put("requestBody", map);

        Map<String, Object> requestHeader = new HashMap<>(10);
        res.put("requestHeader", requestHeader);
        while (headers.hasMoreElements()) {
            String header = headers.nextElement();
            String value = request.getHeader(header);
            requestHeader.put(header, value);
        }
        System.out.println(JSON.toJSONString(res));

        return JSON.toJSONString(res);
    }

}

POM 文件

核心的POM文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

    <properties>
        <java_source_version>1.8</java_source_version>
        <java.version>1.8</java.version>
        <java_target_version>1.8</java_target_version>
        <file_encoding>UTF-8</file_encoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--  和AOP 有關(guān) -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>

        <!--json-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.40</version>
        </dependency>

    </dependencies>

好了,到現(xiàn)在整個(gè)的SpringBoot 項(xiàng)目算是完成了咒林,默認(rèn)了HTTP端口是8080熬拒,運(yùn)行Bootstrap的main方法啟動(dòng)項(xiàng)目,直到最后輸出如下日志信息


image

利用postman工具能夠很方便的測(cè)試我們的項(xiàng)目是否運(yùn)行正常


image
image

到這里整個(gè)的SpringBoot的demo就完成了

2垫竞、展示所有的bean信息

現(xiàn)在提一個(gè)問題澎粟,我們?cè)撊绾潍@取到Spring IOC容器所有的bean信息然后輸出到網(wǎng)頁上?
想要解決這個(gè)問題件甥,那第一點(diǎn)肯定要獲取到Spring IOC容器的上下文捌议,然后從上下文中獲取bean信息,這個(gè)可以由ApplicationContextAware接口的實(shí)現(xiàn)類完成引有,他有一個(gè)set方法瓣颅,可以注入上下文信息,然后獲取該實(shí)現(xiàn)類間接獲取到所有的bean信息就可以了譬正。

SpringApplicationContextAware 文件

public class SpringApplicationContextAware implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 通過這種形式就獲取到了Spring 本身的上下文內(nèi)容了
        // 該方法由spring在aware操作時(shí)調(diào)用宫补,此時(shí)對(duì)象本身已經(jīng)實(shí)例化了
        SpringApplicationContextAware.applicationContext = applicationContext;
    }

    public int getBeanCount() {
        // 獲取了上下文之后,調(diào)用其方法獲取bean的個(gè)數(shù)
        return applicationContext.getBeanDefinitionCount();
    }

    public String[] getBeanName() {
        return applicationContext.getBeanDefinitionNames();
    }
}

然后通過@Bean的形式曾我,注入了SpringContextTool的bean對(duì)象粉怕,緊接著直接調(diào)用getBeanName方法,直接輸出即可抒巢,如下圖就是輸出的bean所有的信息

image

其實(shí)在demo中還有個(gè)使用

3贫贝、HTTP請(qǐng)求 監(jiān)控輸出

這個(gè)其實(shí)是使用了Spring MVC 的publishEvents參數(shù)(默認(rèn)為true),然后利用ServletRequestHandledEvent事件完成,具體可看如下的FrameworkServlet類文件

private void publishRequestHandledEvent(
        HttpServletRequest request, HttpServletResponse response, long startTime, Throwable failureCause) {
    if (this.publishEvents) {
        // 默認(rèn)為true
        long processingTime = System.currentTimeMillis() - startTime;
        int statusCode = (responseGetStatusAvailable ? response.getStatus() : -1);
        this.webApplicationContext.publishEvent(
                new ServletRequestHandledEvent(this,
                        request.getRequestURI(), request.getRemoteAddr(),
                        request.getMethod(), getServletConfig().getServletName(),
                        WebUtils.getSessionId(request), getUsernameForRequest(request),
                        processingTime, failureCause, statusCode));
    }
}

現(xiàn)在我們只需要設(shè)置好ServletRequestHandledEvent的事件監(jiān)聽器就行

public class CustomServletRequestHandledEventRefresh implements ApplicationListener<ServletRequestHandledEvent> {

    @Override
    public void onApplicationEvent(ServletRequestHandledEvent event) {

        FrameworkServlet frameworkServlet = (FrameworkServlet)event.getSource();
        String clientAddress = event.getClientAddress();
        String desc = event.getDescription();
        String methodName = event.getMethod();
        String requestUrl = event.getRequestUrl();
        String servletName = event.getServletName();
        int statusCode = event.getStatusCode();
        long time = event.getTimestamp();

        System.out.println(JSON.toJSONString(event));
        // 打印在控制臺(tái)上
    }
}

然后注冊(cè)該bean即可,他是實(shí)現(xiàn)ApplicationListener接口的稚晚,處理為HTTP請(qǐng)求后由Spring框架自身調(diào)用完成崇堵,輸出的結(jié)果如下圖,還可以設(shè)置異步的線程池異步處理該事件客燕,更多的可以看看

image

4鸳劳、Swagger

swagger是一個(gè)第三方的工具,更多可參考Swagger 官網(wǎng)也搓,這里我們忽略其編輯器的功能赏廓,關(guān)注其界面化的展示最新的API接口文檔并可以進(jìn)行調(diào)用測(cè)試的功能。

POM設(shè)置

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.1</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.6.1</version>
</dependency>

Swagger Bean 設(shè)置

@Bean("swaggerDocker")
public Docket docket() {

    ApiInfo apiInfo = new ApiInfoBuilder()
            .title("Spring Boot Swagger DEMO")
            .description("學(xué)習(xí)swagger")
            .version("1.0")
            .build();

    return new Docket(DocumentationType.SWAGGER_2)
            .apiInfo(apiInfo)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.demo"))
            // API 掃描的包路徑傍妒,一般建議是controller一層即可
            .paths(PathSelectors.any())
            .build();
}

Controller 設(shè)置

目前只介紹ApiOperation幔摸,其實(shí)還有不少參數(shù),更多自行查看官網(wǎng)文檔

@ApiOperation(value = "獲取Spring Bean信息", notes = "Spring Bean")
// 設(shè)置函數(shù)的標(biāo)題拍顷,以及其描述信息

最后在Bootstrap文件加上@EnableSwagger2就完成了整個(gè)的Swagger 工具接入抚太,輸入http://127.0.0.1:8080/swagger-ui.html#/student-controller,可以看到如下圖的接口文檔

image
image

到此整個(gè)的SpringBoot的入門使用就完成了昔案。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尿贫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子踏揣,更是在濱河造成了極大的恐慌庆亡,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捞稿,死亡現(xiàn)場(chǎng)離奇詭異又谋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)娱局,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門彰亥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衰齐,你說我怎么就攤上這事任斋。” “怎么了耻涛?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵废酷,是天一觀的道長。 經(jīng)常有香客問我抹缕,道長澈蟆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任卓研,我火速辦了婚禮趴俘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己哮幢,他們只是感情好带膀,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布志珍。 她就那樣靜靜地躺著橙垢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巩搏。 梳的紋絲不亂的頭發(fā)上银伟,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天蓝纲,我揣著相機(jī)與錄音,去河邊找鬼喂击。 笑死,一個(gè)胖子當(dāng)著我的面吹牛淤翔,可吹牛的內(nèi)容都是我干的翰绊。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼旁壮,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼监嗜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抡谐,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤裁奇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后麦撵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刽肠,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年免胃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了音五。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡羔沙,死狀恐怖躺涝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撬碟,我是刑警寧澤诞挨,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站呢蛤,受9級(jí)特大地震影響惶傻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜其障,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一银室、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦蜈敢、人聲如沸辜荠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伯病。三九已至,卻和暖如春否过,著一層夾襖步出監(jiān)牢的瞬間午笛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國打工苗桂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留药磺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓煤伟,卻偏偏與公主長得像癌佩,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子便锨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理围辙,服務(wù)發(fā)現(xiàn),斷路器鸿秆,智...
    卡卡羅2017閱讀 134,719評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,867評(píng)論 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架酌畜,建立于...
    Hsinwong閱讀 22,445評(píng)論 1 92
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,723評(píng)論 2 22
  • 一份精神一份財(cái),一個(gè)人的好狀態(tài)當(dāng)然也會(huì)吸引一批好狀態(tài)的人考婴,我們常說人和人之間是有磁場(chǎng)的贩虾,那些百萬富翁能成功的原因。...
    瘦朵朵健身閱讀 589評(píng)論 0 1