fundo
Amigos que usam instinto repousante para exportar essas necessidades são rejeitados ~ Destrua a consistência dos URLs repousantes [a correção estrita é HTTP JSON ou RESTful. Muitos amigos vão expor um JSON e chamá -lo de repouso diretamente]
Como no gerador de código acima, vamos gerar um monte de códigos, a maioria dos quais são Controladores Rest.
Classe abstrata pública abstractrestController <v estende Vo, S estende SO, PK estende serializável> {classe protegida <V> voclazz; @AUTOWIRED SERVIÇO PRIVADO <V, S, PK> Service; public abbtracTrestController () {typeToken <V> VotyPy = new TypeToken <V> (getClass ()) {}; voclazz = (classe <V>) votype.getrawtype (); } @PostMapping () @apioperation (value = "nova entidade", notas = "") resultado público add (@Requestbody v vo) {service.SaveSelective (VO); return resultGenerator.GensuccessResult (); } @Deleletemapping ("/{id}") @apioperation (value = "excluir entidade", notas = "") Resultado público delete (@pathvariable pk id) {service.deletebyId (id); return resultGenerator.GensuccessResult (); } @PutMapping @apioperation (value = "Atualizar entidade", notas = "") Atualização do resultado público (@Requestbody v vo) {Service.UpDateByPrimaryKeySelective (VO); return resultGenerator.GensuccessResult (); } @GetMapping @apioperation (value = "get entity list", NOTS = "") Lista de resultados públicos (S SO) {PageHelper.StartPage (SO.GetCurrentPage (), SO.getPagesize ()); List <V> List = Service.findall (); PageInfo PageInfo = new PageInfo (lista); excelexportParam (); return resultGenerator.GensuccessResult (PageInfo); } void protegido excelexportParam () {exportParams ep = new ExportParams (null, "dados"); ExcelexportParam <V> param = new ExcelexportParam <> (); param.setClazz (voclazz); param.setexcelExport (excelexport.normalexcel); param.setexportParams (EP); param.setFilename ("file.xls"); F6static.setexcelExportParam (param); } @GetMapping ("/{id}") @apioperation (value = "get entidade única", notas = ""). Retornar resultadoGenerator.GensuccessResult (VO); } @Deleletemapping ("/batch") @apioperation (value = "entidade de exclusão em lote", notas = "") resultado público BatchDelete (@RequestParam String Ids) {Service.deleteByIds (IDS); return resultGenerator.GensuccessResult (); } @GetMapping ("/batch") @apioperation (value = "lote get entity", notas = "") public resultado BatchDetail (@RequestParam String Ids) {list <V> vos = service.findbyids (ids); RETORNO RESULTGenerator.GensuccessResult (VOS); } @PostMapping ("/batch") @apioperation (value = "lote nova entidade", notas = "") resultado público add (@requestbody list <V> vos) {service.save (vos); return resultGenerator.GensuccessResult (); } @GetMapping ("/count") @apioperation (value = "obtenha o número de entidades", notas = "" ") contagem de resultados públicos (@requestbody v v) {int count = service.leclectCount (v); retorno resultGenerator.GensuccessResult (contagem); }Então, como exportar? [De fato, pode -se entender que a exportação é a exibição de dados, mas o resultado não é apenas JSON]
Se uma pergunta é levantada, e que tal fazer login? As soluções tradicionais são login de login. Então, qual é a ideia de substituir os recursos RESTful?
Dica: o login é a nova sessão. Logout é a sessão de exclusão.
concluir
Com base nas idéias acima, naturalmente pensamos que precisamos apenas retornar vários resultados ao mesmo URL, não está ok? [PDF, uma versão, uma versão, uma versão, uma versão, uma versão, uma versão]
Bingo! Esta é a origem do negociador de conteúdo
O negociador de conteúdo não foi criado pela primavera, de fato, isso pode ser visto no cabeçalho HTTP.
1. Por exemplo, retornar à página em inglês para o cliente inglês é demais para a página chinesa.
O protocolo HTTP define valores de qualidade (referidos como valores Q) que permitem que os clientes listem várias opções para cada categoria de preferência e associam uma prioridade a cada opção de preferência.
Aceitar-Language: en; q = 0,5, fr; q = 0,0, nl; q = 1,0, tr; q = 0,0
Onde o valor q varia de 0,0 a 1,0 (0,0 é a menor prioridade, enquanto 1,0 é a prioridade mais alta).
Observe que a ordem das preferências não é importante, apenas o valor q relacionado às preferências é importante
2. Depois, existem outros parâmetros, como o cabeçalho de aceitação
Geralmente, o negociador de conteúdo primeiro tem as seguintes soluções
1.Use aceitar o cabeçalho:
Este é comumente descrito nos livros didáticos. Idealmente, esse método é o melhor, mas se seus recursos forem acessados diretamente através do navegador (ou seja, exibição HTML), devido a diferenças de navegador, o cabeçalho aceita enviado será diferente. Isso fará com que o servidor não saiba qual formato de dados retornar a você. A seguir, o cabeçalho aceita do navegador
Chrome: aceite: aplicação/xml, aplicação/xhtml+xml, textml; q = 0,9, texto/liso; q = 0,8, imagem/png,*/*; q = 0.5 firefox: aceite: text/html, aplicação/xhtml+xml, aplicação/xml; q = 0,9,*/*/*; Image/PJPEG, Application/X-Shockwave-Flash, Application/X-Silverlight, Application/X-Ms-Aplicação, Application/X-Ms-XBap, Application/Vnd.MS-XpsDocument, Application/Xaml+Xml, */ *
2. Use extensão
O mesmo URL foi perdido, mas esse método é mais usado no ambiente real, porque está mais alinhado com a visão estética dos programadores.
Por exemplo, /user.json /User.xls /User.xml
Usando parâmetros agora muitas APIs abertas usam esse método, como o Taobao
No entanto, para diferentes navegadores, o cabeçalho aceita pode não ser particularmente unificado, muitas implementações escolhem 2 3 duas soluções.
Adotamos as duas soluções acima na primavera
Primeiro configure o negociador de conteúdo
Código
@Bean public ViewResolver ContentNegoTiatingViewResolver (ContentNegoTiationManager Gerenciador) {// Defina o View Resolvers ViewResolver BeanNameViewResolver = new BeanNameViewResolver (); List <ViewResolver> resolvedores = lists.newArrayList (BeanNameViewResolver); ContentNegoTiatingViewResolver resolver = new ContentNegoTiatingViewResolver (); resolver.setViewResolvers (resolvedores); resolver.setContentNegoTiationManager (gerente); Retornar resolvedor; } @Override public void ConfigureContentNeGoTiation (ContentNegoTiationConfigurer Configure) {Configurer.FavorPathExtension (true) .usejaf (false) .FavorParameter (true) .parametername ("formato") .IgnoreAcCcetHeader (true). .mediatype ("json", mediatype.application_json) .mediatype ("xls", excel_media_type); }Crie o conversor correspondente
private httpmessageConverter <ject> createExcelHttpMessageConverter () {ExcelHttpMessageConverter ExcelHttpMessageConverter = new ExcelHtttpMessageConverter (); retornar excelHttpMessageConverter; }Exportar dados diretamente usando o Easy-POI
/ * * Copyright (c) 2017. Lorem ipsum dolor sit amet, consistur adipiscing elit. * Morbi non Lorem Porttitor Neque Feugiat Blandit. Ut vitae ipsum eget quam lacinia accumsan. * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas Magna. * Proin dapibus sapien vel. Aliquam Erat Volutpat. Plelentresque Sagittis Ligula Eget Metus. * Commodo vestibular. Ut Rhoncus Gravida Arcu. */ pacote com.f6car.base.web.converter; importar cn.afterturn.easypoi.excel.excexportutil; importar com.f6car.base.common.result; importar com.f6car.base.core.excexport; importar com.f6car.base.core.excexportParam; importar com.github.pagehelper.pageinfo; importar com.google.common.collect.lists; importar org.apache.poi.ss.usermodel.workbook; importar org.springframework.http.httpheaders; importar org.springframework.http.httpinputMessage; importar org.springframework.http.httputputMessage; importar org.springframework.http.mediType; importar org.springframework.http.converter.abstracthttpmessageConverter; importar org.springframework.http.converter.generichttpmessageConverter; importar org.springframework.http.converter.httpmessageNotReadableException; importar org.springframework.http.converter.httpmessageNotwritableException; importar java.io.ioException; importar java.lang.reflect.type; importar java.net.urlencoder; importar java.util.Collection; importar java.util.Collections; importar java.util.Collections; importar java.util.map; importar estático com.f6car.base.core.f6static.getexcelExportParam; /** * @author qixiaobo */ public class ExcelHttpMessageConverter extends AbstractHttpMessageConverter<Object> implements GenericHttpMessageConverter<Object> { public static final MediaType EXCEL_MEDIA_TYPE = new MediaType("application", "vnd.ms-excel"); public excelHttpMessageConverter () {super (Excel_Media_Type); } @Override Protected Boolean Supports (classe <?> Clazz) {return false; } @Override Protected Object ReadInternal (classe <?> Clazz, httpinputMessage inputMessage) lança IoException, httpMessageNotableAltableException {return null; } @Override Protected void WriteInternal (objeto o, httpOutputMessage OutputMessage) lança IoException, httpMessageNotWritableException {httpheaders headers = outputMessage.getheaders (); Dados de coleta = getActualData ((resultado) o); ExcelexportParam excelexportParam = getExcexportParam (); Pasta de trabalho; switch (excelexportParam.getexcelExport ()) {case normalexcel: workbook = excelexportutil.exportExcel (excelexportParam.getexportParams (), (classe <?>)) quebrar; case mapexcel: workbook = excelexportutil.exportExcel (excelexportParam.getexportParams (), excelexportParam.getexceLexportentities (), (coleção <? estende o mapa <?,? >>) dados); quebrar; Case BigExcel: Case MapExcelGraph: Case PDFTEMPLATE: CASE METEMPLEEXCEL: CASE MEMPLEMWORD: PADRÃO: LONGE NOVA RUNTIMEIXCECCECTION (); } if (Book! headers.setContentDisPoitionFormData ("anexo", codedFileName); } Work.write (outputMessage.getBody ()); }} coleção particular getActualData (resultado r) {if (r! if (data instanceof PageInfo) {return ((PageInfo) data) .getList (); } else if (! (Instância de dados da coleção)) {data = lists.newArrayList (dados); } else {return (collection) dados; }} Return Collection.Emptylist (); } @Override public boolean CanRead (tipo tipo, classe <?> ContextClass, mediatype mediatype) {// Excel Return false não é suportado; } @Override Public Object Read (Tipo Tipo, classe <?> ContextClass, httpinputMessage inputMessage) lança IoException, httpMessageNotableAltableException {return null; } @Override public boolean canwrite (tipo tipo, classe <?> Clazz, mediatype mediatype) {return super.canwrite (mediatype) && clazz == result.class && support (); } private boolean support () {excelexportParam param = getExcelExportParam (); if (param == null || param.getexceLexport () == null || param.getexportParams () == null) {return false; } if (param.getexceLexport () == Excexport.Normalexcel) {return true; } else {Logger.warn (param.getexcelExport () + "não suporta agora!"); retornar falso; }} @Override public void Write (objeto o, tipo tipo, MediaType ContentType, httputputMessage outputMessage) lança IoException, httpMessageNotWritabledException {Super.Write (O, ContentType, outputMessage); }}Por enquanto, é apenas para exportação, então quando usado da seguinte maneira
@GetMapping @apioperation (value = "Get Entity List", NOTS = "") Lista de resultados públicos (S SO) {PageHelper.StartPage (SO.GetCurrentPage (), So.getPagesize ()); List <V> List = Service.findall (); PageInfo PageInfo = new PageInfo (lista); excelexportParam (); return resultGenerator.GensuccessResult (PageInfo); } void protegido excelexportParam () {exportParams ep = new ExportParams (null, "dados"); ExcelexportParam <V> param = new ExcelexportParam <> (); param.setClazz (voclazz); param.setexcelExport (excelexport.normalexcel); param.setexportParams (EP); param.setFilename ("file.xls"); F6static.setexcelExportParam (param); }Quando visitamos
http://127.0.0.1:8079/zeus/user
{"Code": 200, "Data": {"Endrow": 10, "FirstPage": 1, "HasNextPage": True, "HaspreviousPage": false, "isfirstpage": true, "Islastpage": "False," Lastpage ": 8," List ": [{" Cellphone ":" 135: "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135" 135 "135:" 1350: "40POLETA "450:" ÍsmemPraget ":" ISLASTPAGE ":" False, "lastpage": 8 ": 24201883434352650, "IDOWNORG": 23993199378825296, "IDROLE": 88, "IDWXBSTATION": "332", "IDWXBUSER": "207," ISadMin ": 1," Isdel "0," é ":" 207, "isadmin": 1, "isdel" 0, "é" "é" ":" Idwxbuser ":" 207, "isadmin": 1, "Isdel" 0, "é" "é" ":" IDWxBUser ":" 207, "isadmin": 1, "Isdel" 0, "é": "207," isadmin ": 1," Isdel "0," é "". "", "Senha": "96E79218965EB72C92A549DD5A330112", "PKID": 23993199378825296, "Username": "Lingweiqiche"}, {"Cellphone": "": "Idemplo "idRole": 4, "idWxbStation": "", "", "idWxbUser": "", "isAdmin": 0, "isDel": 0, "isGuideOpen": 0, "limitMac": 0, "openid": "", "password": "96e79218965eb72c92a549dd5a330112", "PKID": 24201883434356532, "Nome de usuário": "007"}, {"celular": "15715139000", "idemployee": 24351585207523460, "idOWNORG": 242018834443777777776760, "IDOWNORG": 242018834443777777575760, "IDOWNRG": 2420188344437777757523460, "IDOWNORG": 24201883444377777757575460. "540", "idWxbUser": "298", "isAdmin": 1, "isDel": 0, "isGuideOpen": 0, "limitMac": 0, "openid": "", "password": "96e79218965eb72c92a549dd5a330112", "pkId": 24201883434357600, "Nome de usuário": "15715139000"}, {"celular": "", "idemployee": 0, "idOWNorg": 24201883434357600, "IdRole" 216, "IDWXBSTATION": "" IDWXB ""; "ISDEL": 0, "ISGUIDEOPEN": 0, "LIMITMAC": 0, "OpenId": "", "Senha": "96E79218965EB72C92A549DD5A330112", "PKID": 242018343434357920, "usining": "Usling". "IDEMPLAZEE": 24351585207425676, "IDOWNORG": 24201883434359384, "IdRole": 90, "IDWXBStation": "348", "IDWXBUSER": "227", "é" isadmin ": 1," é 0, "openid": "opzUDs_v13WE500kxYMj6Xg_gFeE", "password": "96e79218965eb72c92a549dd5a330112", "pkId": 24201883434359388, "username": "15952920979" }, { "cellPhone": "", "idEmployee": 0, "idOwnOrg": 24201883434359790, "idRole": 91, "idWxbStation": "315", "idWxbUser": "175", "isAdmin": 1, "isDel": 0, "isGuideOpen": 0, "limitMac": 0, "openid": "", "password": "96e79218965eb72c92a549dd5a330112", "pkId": 24201883434359790, "username": "13809056211" }, { "cellPhone": "18903885585", "idEmployee": 24201883434366164, "IDOWNORG": 24201883434359890, "IDROLE": 92, "IDWXBSTATION": "317", "IDWXBUSER": "178," isadmin ": 1," Isdel "0," Isgur ":" 178, "isadmin": 1, "Isdel" 0, "Isgur": "178," isadmin ": 1," Isdel "0," IsGer ":" 178, "Isadmin": 1, "Isdel": "", "Senha": "96E79218965EB72C92A549DD5A330112", "PKID": 24201883434359892, "Nome de usuário": "18903885585"}, {"celular": "" "" "": "idOwnOrg": 24201883434359924, "idRole": 93, "idWxbStation": "318", "idWxbUser": "179", "isAdmin": 1, "isDel": 0, "isGuideOpen": 0, "limitMac": 0, "openid": "", "password": "96E79218965EB72C92A549DD5A330112", "PKID": 24201883434359930, "Nome de usuário": "13372299595"}, {"Cellg": "", "idemployee": 0, "}," ":" "," Idemployee ": 0,"}}, "": "", "Idemployee": 0, " "IdRole": 94, "IDWXBSTATION": "321", "IDWXBUSER": "188", "ISADMIN": 1, "ISDEL": 0, "ISGUideopen": 0, "limiteMac": 0, "OpenId": "Password": "96e7921820: "pkId": 24201883434360052, "username": "15221250005" }, { "cellPhone": "", "idEmployee": 0, "idOwnOrg": 24201883434360070, "idRole": 95, "idWxbStation": "325", "idWxbUser": "198", "isAdmin": 1, "isDel": 0, "isGuideOpen": 0, "limitMac": 0, "openid": "", "password": "96e79218965eb72c92a549dd5a330112", "pkId": 24201883434360070, "username": "13837251167" } ], "navigateFirstPage": 1, "navigateLastPage": 8, "navigatePages": 8, "navigatepageNums": [ 1, 2, 3, 4, 5, 6, 7, 8 ], "nextPage": 2, "orderBy": "", "pageNum": 1, "pageSize": 10, "pages": 102, "prePage": 0, "size": 10, "Startrow": 1, "Total": 1012}, "Mensagem": "Success"}Ao acessar http://127.0.0.1:8079/zeus/user?format=xls ou http://127.0.0.1:8079/zeus/user.xls
Os seguintes efeitos
Como os dados aqui estão relacionados à consulta, podemos operar dessa maneira http://127.0.0.1:8079/zeus/user.xls?pagesize=1000 Realizar facilmente xlsization of Query Results!
Resumir
O exposto acima é uma ilustração do negociador de conteúdo no Springboot apresentado a você pelo editor. Espero que seja útil para você. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a você a tempo. Muito obrigado pelo seu apoio ao site wulin.com!