跟着JHipster學做項目 (7) swagger-ui展現

前面講過使用Swagger2生成API文檔,這裏是關於直接在瀏覽器中展示API,並且可以在線測試API。着重從三個方面來概括一下swagger-ui展現:

  1. Spring Boot端如何啓動swagger, 使後端可以接收/v2/api-docs和/swagger-resources請求,並返回相應的response(swagger.json, {url, name}).
  2. swagger-ui的前端代碼生成
  3. Spring Boot後端和Vue前端如何處理請求的權限

JHipster通過引入jhipster-framework來啓動swagger

        <dependency>
            <groupId>io.github.jhipster</groupId>
            <artifactId>jhipster-framework</artifactId>
        </dependency>

在io.github.jhipster.config.apidoc.SwaggerAutoConfiguration類中利用註解@EnableSwagger2啓動swagger提供的兩個服務,這裏要注意,啓動swagger設定了兩個條件:

第一, profiles中必須包含swagger

第二,必須引入依賴springfox-swagger2, springfox-bean-validators,由於之前生成API文檔的項目中是通過測試類生成swagger.json文件,通常會把scope設成test, 這裏一定要去掉,否則swagger無法啓動。

SwaggerAutoConfiguration類中包含了@Configuration註解,此外在/META-INF/spring.factories文件中配置了spring boot auto configuration

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  io.github.jhipster.config.apidoc.SwaggerAutoConfiguration,\
  io.github.jhipster.config.apidoc.SwaggerPluginsAutoConfiguration,\
  io.github.jhipster.config.JHipsterProperties,\
  io.github.jhipster.security.uaa.UaaAutoConfiguration,\
  io.github.jhipster.config.info.JHipsterInfoContributorConfiguration,\
  io.github.jhipster.config.metric.JHipsterMetricsEndpointConfiguration,\
  io.github.jhipster.config.metric.JHipsterLoggingMetricsExportConfiguration,\
  io.github.jhipster.security.ssl.UndertowSSLConfiguration

這樣當spring boot啓動的時候自動尋找第三方jar包中META-INF/spring.factories文件中的配置,自動加載jar包中相關配置,所以只要引入jhipster-framework, 並且profiles中包含swagger, swagger就可以成功啓用,

spring:
  profiles:
    active: dev
    include:
      - swagger

檢測swagger是否成功啓用可以通過設定調試模式,來觀察啓動時日誌是否包含swagger啓動信息: Started Swagger in 6 ms

logging:
  level:
    ROOT: DEBUG
    io.github.jhipster: DEBUG
    com.mycompany.myapp: DEBUG
    org.springframework.web: DEBUG
    org.springframework.security: DEBUG

JHipster關於swagger權限控制後端有三個方面:

首先,對於swagger-ui/index.html頁面的訪問權限設定如下:

 @Override
    public void configure(WebSecurity web) {
        web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .antMatchers("/app/**/*.{js,html}")
            .antMatchers("/i18n/**")
            .antMatchers("/content/**")
            .antMatchers("/swagger-ui/index.html")
            .antMatchers("/test/**");
    }

然後是比較巧妙的方式來設定對/v2/api-docs和/swagger-resources的訪問,

            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/account/reset-password/init").permitAll()
            .antMatchers("/api/account/reset-password/finish").permitAll()
            .antMatchers("/api/**").authenticated()

可以看到在安全配置中只對/api/**做了權限控制,這間接意味着可以對/v2/api-docs和/swagger-resources進行訪問,而通常我們都是寫成:

antMatchers("/**").authenticated()

最後對跨域訪問的處理如下:

            source.registerCorsConfiguration("/api/**", config);
            source.registerCorsConfiguration("/management/**", config);
            source.registerCorsConfiguration("/v2/api-docs", config);

Vue前端安全處理是在請求中額外添加token信息

requestInterceptor: function(req) {
                    var authToken = localStorage.getItem("jhi-authenticationToken")
                        || sessionStorage.getItem("jhi-authenticationToken");
                    if (authToken) {
                        req.headers['Authorization'] = "Bearer " + authToken;
                    }
                    return req;
                }

JHipster沒有在後端引入關於swagger-ui依賴,而是將swagger-ui代碼放置在vue代碼中,動態設定index.html中urls信息

var urls = [];
        axios.get("/swagger-resources").then(function (response) {
            response.data.forEach(function (resource) {
                urls.push({"name": resource.name, "url": resource.location});
            });

            urls.sort(function (a, b) {
                var x = a.name.toLowerCase(), y = b.name.toLowerCase();
                return x < y ? -1 : x > y ? 1 : 0;
            });

            // Build a system
            var ui = SwaggerUIBundle({
                urls: urls,
                dom_id: '#swagger-ui',
                deepLinking: true,
                filter: true,
                layout: "StandaloneLayout",
                withCredentials: true,
                presets: [
                    SwaggerUIBundle.presets.apis,
                    SwaggerUIStandalonePreset
                ],
                plugins: [
                    SwaggerUIBundle.plugins.DownloadUrl
                ],
                requestInterceptor: function(req) {
                    var authToken = localStorage.getItem("jhi-authenticationToken")
                        || sessionStorage.getItem("jhi-authenticationToken");
                    if (authToken) {
                        req.headers['Authorization'] = "Bearer " + authToken;
                    }
                    return req;
                }
            });

此文件經過webpack打包生成最終swagger-ui/index.html文件

const CopyWebpackPlugin = require('copy-webpack-plugin');   
 new CopyWebpackPlugin([
      { from: './node_modules/swagger-ui-dist/*.{js,css,html,png}', to: 'swagger-ui', flatten: true, ignore: ['index.html'] },
      { from: './node_modules/axios/dist/axios.min.js', to: 'swagger-ui' },
      { from: './src/main/webapp/swagger-ui/', to: 'swagger-ui' },
      { from: './src/main/webapp/content/', to: 'content' },
      { from: './src/main/webapp/favicon.ico', to: 'favicon.ico' },
      {
        from: './src/main/webapp/manifest.webapp',
        to: 'manifest.webapp'
      },
      // jhipster-needle-add-assets-to-webpack - JHipster will add/remove third-party resources in this array
      { from: './src/main/webapp/robots.txt', to: 'robots.txt' }
    ]),

最後我們會在瀏覽器中看到API列表:

swagger

Good Luck,

Cheers!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章