Как разрешить просмотр в thymleaf + Springboot? - PullRequest
0 голосов
/ 02 июля 2018

В настоящее время у меня есть функция, которая заключается в преобразовании данных из MYSQL в CSV. Функция CSV содержит webconfig, где используется viewResolver. Проблема в том, что, когда я использовал функцию ниже, страница не может быть просмотрена, но файл CSV может быть загружен и наоборот. Что-нибудь, что мне нужно настроить?

-Конфигурировать ContentNegotiatingViewResolver

  @Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {

ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);

// Define all possible view resolvers
List<ViewResolver> resolvers = new ArrayList<>();

resolvers.add(csvViewResolver());
    resolver.setViewResolvers(resolvers);
    return resolver;
}

WebConfig - полный код

    package com.portal.dmtt.csvDownload.config;

import com.portal.dmtt.csvDownload.viewResolver.CsvViewResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
                .defaultContentType(MediaType.APPLICATION_JSON)
                .favorPathExtension(true);
    }
    /*
     * Configure ContentNegotiatingViewResolver
     */
    @Bean
    public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
        ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
        resolver.setContentNegotiationManager(manager);

        // Define all possible view resolvers
        List<ViewResolver> resolvers = new ArrayList<>();

        resolvers.add(csvViewResolver());
        resolver.setViewResolvers(resolvers);
        return resolver;
    }

    /*
     * Configure View resolver to provide Csv output using Super Csv library to
     * generate Csv output for an object content
     */
    @Bean
    public ViewResolver csvViewResolver() {
        return new CsvViewResolver();
    }



}

Контроллер экспорта

package com.portal.dmtt.csvDownload.controller;

import com.portal.dmtt.repo.dmttDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ExportController {

    @Autowired
    private dmttDAO dmttDAO;

    /**
     * Handle request to download an Excel document
     */
    @GetMapping("/dl")
    public String download(Model model) {

        model.addAttribute("results", dmttDAO.getAllResultSet());
        return "";
    }

}

Абстрактный вид

package com.portal.dmtt.csvDownload.view;

 import org.springframework.web.servlet.view.AbstractView;

 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.Map;

 public abstract class AbstractCsvView extends AbstractView {

     private static final String CONTENT_TYPE = "text/csv";

     public AbstractCsvView() {
         setContentType(CONTENT_TYPE);
     }

     @Override
     protected boolean generatesDownloadContent() {
         return true;
     }


     @Override
     protected final void renderMergedOutputModel(
             Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
         response.setContentType(getContentType());
         buildCsvDocument(model, request, response);
     }

     protected abstract void buildCsvDocument(
             Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
             throws Exception;


 }

CSV View

package com.portal.dmtt.csvDownload.view;

import com.portal.dmtt.model.exceptionMonitoring.FN_Result_Set;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

public class CsvView extends AbstractCsvView {


    @Override
    protected void buildCsvDocument(Map<String, Object> model, HttpServletRequest request, HttpServletResponse
            response) throws Exception {

        response.setHeader("Content-Disposition", "attachment; filename=\"my-csv-file.csv\"");

        List<FN_Result_Set> fnResultSetList = (List<FN_Result_Set>) model.get("results");

        String[] header = {"SP_ID", "SP_ID", "XFER_XMIT_STATUS", "XFER_FILE_NAME", "UPDATE_TS", "YYMM", "REMARKS"};

        try {

            ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(),
                    CsvPreference.STANDARD_PREFERENCE);

            csvWriter.writeHeader(header);

            for (FN_Result_Set user : fnResultSetList) {
                csvWriter.write(user, header);
            }
            csvWriter.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Просмотр резольвера

package com.portal.dmtt.csvDownload.viewResolver;

import com.portal.dmtt.csvDownload.view.CsvView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

import java.util.Locale;

public class CsvViewResolver implements ViewResolver {

    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {

        return new CsvView();
    }
}

1 Ответ

0 голосов
/ 02 июля 2018

Одна из проблем заключается в том, что ваш CSVViewResolver разрешает представление для любого имени представления. Возможно, вы захотите вернуть null из CSVViewResolver.resolveViewName(), если s, имя представления, не пустое.

Другая проблема заключается в том, что браузер (по крайней мере, мой Chrome) не отправляет text/csv в качестве заголовка Accept, но text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Установите тип носителя явно в configureContentNegotiation для CSV :

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer
            .defaultContentType(MediaType.APPLICATION_JSON)
            .favorPathExtension(true)
            .mediaType("csv", MediaType.parseMediaType("text/csv"));
}

Удалите содержимое компонента BeegotiatingViewResolver

Не следует создавать contentNegotiatingViewResolver, поскольку он предоставляется Spring Boot. Если вы предоставите один, у вас будет два этого типа, и у вас не будет Thymeleaf ViewResolver. Поскольку ваш CSVViewResolver вернет представление для любого имени представления, оно будет разрешено в предоставленном вами ContentNegotiatingViewResolver, а не в предоставленном Spring.


подробности:

Боб csvViewResolver будет поднят весенним ботинком ContentNegotiatingViewResolver вместе с другими, такими как BeanNameViewResolver, ThymeleafViewResolver, ViewResolverComposite, InternalResourceViewResolver.

Для отладки установите точку останова на DispatcherServlet.resolveViewName:

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
        HttpServletRequest request) throws Exception {

    for (ViewResolver viewResolver : this.viewResolvers) {
        View view = viewResolver.resolveViewName(viewName, locale);
        if (view != null) {
            return view;
        }
    }
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...