Şirket projesinin bir gereksinimi vardır. Ön uç excel dosyalarını yükler, arka uç verileri okur, verileri işler ve hata verilerini döndürür. En basit yol, işlemeyi senkronize etmektir. Dosyaları yükledikten sonra, istemcinin yanıt beklemesi engellendi, ancak kullanıcı deneyimi şüphesiz zayıf, veri işliyor Çok zaman alabilir, kimse beklemeye istekli olmayabilir çünkü proje ActiveMQ ve diğer mesaj kuyruğu ara yazılımlarını kullanmadı ve redis'in lpush ve rpop'u hafif bir mesaj kuyruğu uygulaması olarak çok uygundur, bu yüzden fonksiyon geliştirmeyi tamamlamak için kullanın
Tabii ki Java uygulaması
Dahil olan birçok bilgi noktası vardır ve her bilgi noktası, öğrenme ve analiz için bir konu olarak kullanılabilir. Bu makale, tam farkındalığı sunacak ve daha sonra öğrenimi arkadaşlarla paylaşacak ve paylaşacaktır.
Not: DAO veritabanı katmanı, bu makalenin odak noktası yerine başka bir modüle yerleştirilmiştir.
1. kolay excel
< easyexcel-latestVersion > 1.1.2-beta4 < / easyexcel-latestVersion > < bağımlılık > < Grup kimliği > com.alibaba < /Grup kimliği > < artifactId > Easyexcel < / artifactId > < versiyon > $ {easyexcel-latestVersion} < / version > < /bağımlılık >2. JWT
< bağımlılık > < Grup kimliği > io.jsonwebtoken < /Grup kimliği > < artifactId > jjwt < / artifactId > < versiyon > 0.7.0 < / version > < /bağımlılık >3. redis
< bağımlılık > < Grup kimliği > org.springframework.boot < /Grup kimliği > < artifactId > Spring-boot-starter-redis < / artifactId > < versiyon > 1.3.5. YAYIN < / version > < /bağımlılık >4. Tencent çünkü
< bağımlılık > < Grup kimliği > com.qcloud < /Grup kimliği > < artifactId > cos_api < / artifactId > < versiyon > 5.4.5 < / version > < /bağımlılık >1. Dosyaları yükleyin
2. Veritabanı içe aktarma kayıtları
3. İçe aktarılan veriler
4. Yanlış dosyayı indirin
5. Yanlış veri istemi
6. Sorgu içe aktarma kayıtları
1. Excel kontrol katmanını içe aktarın
@Oturum açmak gereklidir @RequestMapping (value = "doImport", yöntem = RequestMethod.POST) publicJsonResponsedoImport (@RequestParam ("file") MultipartFilefile, HttpServletRequestrequest) { PLUseruser = getUser (istek); returnorderImportService.doImport (dosya, kullanıcı.getId ()); }2. Hizmet katmanı
@Override publicJsonResponsedoImport (MultipartFilefile, IntegeruserId) { eğer (null == dosya || file.isEmpty ()) { thrownewServiceException ("Dosya boş olamaz"); } Stringfilename = file.getOriginalFilename (); eğer (! checkFileSuffix (dosya adı)) { thrownewServiceException ("Şu anda yalnızca xlsx biçiminde excel'i destekliyor"); } //Dosyaları saklama StringfileId = saveToOss (dosya); if (StringUtils.isBlank (fileId)) { thrownewServiceException ("Dosya yükleme başarısız oldu, lütfen daha sonra tekrar deneyin"); } // Kaydı veritabanına kaydedin saveRecordToDB (kullanıcı kimliği, dosya kimliği, dosya adı); // Bir sipariş içe aktarma mesajı oluşturun redisProducer.produce (RedisKey.orderImportKey, fileId); returnJsonResponse.ok ("Alma başarılı, işleniyor ..."); } / ** * Dosya formatını doğrulayın * @ paramfileName *@dönüş * / privatestaticbooleancheckFileSuffix (StringfileName) { if (StringUtils.isBlank (dosyaAdı) || dosyaAdı.lastIndexOf (".") < = 0) { yanlış dönüş; } intpointIndex = fileName.lastIndexOf ("."); Stringsuffix = dosyaAdı.substring (pointIndex, dosyaAdı.length ()). ToLowerCase (); eğer (". xlsx" .equals (sonek)) { dönüş; } yanlış dönüş; } / ** * Dosyaları Tencent OSS'de saklayın * @ paramfile *@dönüş * / privateStringsaveToOss (MultipartFilefile) { InputStreamins = boş; Deneyin{ ins = file.getInputStream (); } catch (IOExceptione) { e.printStackTrace (); } StringfileId; Deneyin{ StringoriginalFilename = file.getOriginalFilename (); Filef = newFile (orijinalFilename); inputStreamToFile (ins, f); FileSystemResourceresource = newFileSystemResource (f); MultiValueMap < Dize, Nesne > param = newLinkedMultiValueMap < > (); param.add ("dosya", kaynak); ResponseResultresponseResult = restTemplate.postForObject (txOssUploadUrl, param, ResponseResult.class); fileId = (Dize) responseResult.getData (); } catch (Exceptione) { fileId = boş; } returnfileId; }3. Redis üreticisi
@Hizmet publicclassRedisProducerImplimplementsRedisProducer { @Autowired privateRedisTemplateredisTemplate; @Override publicJsonResponseproduce (Stringkey, Stringmsg) { Harita < Dize, Dize > map = Maps.newHashMap (); map.put ("fileId", msg); redisTemplate.opsForList (). leftPush (anahtar, harita); returnJsonResponse.ok (); } }4. Redis tüketicileri
@Hizmet publicclassRedisConsumer { @Autowired publicRedisTemplateredisTemplate; @Value ("$ {txOssFileUrl}") privateStringtxOssFileUrl; @Value ("$ {txOssUploadUrl}") privateStringtxOssUploadUrl; @Filmdenkare publicvoidinit () { processOrderImport (); } / ** * İşlem siparişi içe aktarımı * / privatevoidprocessOrderImport () { ExecutorServiceexecutorService = Executors.newCachedThreadPool (); executorService.execute (() - > { while (true) { Objectobject = redisTemplate.opsForList (). RightPop (RedisKey.orderImportKey, 1, TimeUnit.SECONDS); if (null == nesne) { devam et; } Stringmsg = JSON.toJSONString (nesne); executorService.execute (newOrderImportTask (msg, txOssFileUrl, txOssUploadUrl)); } }); } }5. Görev dizisi sınıfını işleme
publicclassOrderImportTaskimplementsRunnable { publicOrderImportTask (Stringmsg, StringtxOssFileUrl, StringtxOssUploadUrl) { this.msg = msg; this.txOssFileUrl = txOssFileUrl; this.txOssUploadUrl = txOssUploadUrl; } } / ** * Fasulyeyi enjekte edin * / privatevoidautowireBean () { this.restTemplate = BeanContext.getApplicationContext (). getBean (RestTemplate.class); this.transactionTemplate = BeanContext.getApplicationContext (). getBean (TransactionTemplate.class); this.orderImportService = BeanContext.getApplicationContext (). getBean (OrderImportService.class); } @Override publicvoidrun () { // Fasulye enjekte edin autowireBean (); JSONObjectjsonObject = JSON.parseObject (msg); StringfileId = jsonObject.getString ("fileId"); MultiValueMap < Dize, Nesne > param = newLinkedMultiValueMap < > (); param.add ("id", fileId); ResponseResultresponseResult = restTemplate.postForObject (txOssFileUrl, param, ResponseResult.class); StringfileUrl = (Dize) responseResult.getData (); if (StringUtils.isBlank (fileUrl)) { dönüş; } InputStreaminputStream = HttpClientUtil.readFileFromURL (fileUrl); Liste < Nesne > list = ExcelUtil.read (inputStream); süreç (liste, dosya kimliği); } / ** * Dosyaları oss'e yükleyin * @ paramfile *@dönüş * / privateStringsaveToOss (Filefile) { StringfileId; Deneyin{ FileSystemResourceresource = newFileSystemResource (dosya); MultiValueMap < Dize, Nesne > param = newLinkedMultiValueMap < > (); param.add ("dosya", kaynak); ResponseResultresponseResult = restTemplate.postForObject (txOssUploadUrl, param, ResponseResult.class); fileId = (Dize) responseResult.getData (); } catch (Exceptione) { fileId = boş; } returnfileId; }Not: Verileri işlemek için iş mantığı kodunu göndermeye gerek yoktur
6. Dosyaları cos'a yükleyin
@RequestMapping ("/ txOssUpload") @Kafadergisi publicResponseResulttxOssUpload (@RequestParam ("file") MultipartFilefile) throwsUnsupportedEncodingException { eğer (null == dosya || file.isEmpty ()) { returnResponseResult.fail ("Dosya boş olamaz"); } StringoriginalFilename = file.getOriginalFilename (); originalFilename = MimeUtility.decodeText (originalFilename); // Çince bozuk problemi çözün StringcontentType = getContentType (orijinalFilename); Stringkey; InputStreamins = boş; Filef = boş; Deneyin{ ins = file.getInputStream (); f = newFile (orijinalFilename); inputStreamToFile (ins, f); key = iFileStorageClient.txOssUpload (newFileInputStream (f), originalFilename, contentType); } catch (Exceptione) { returnResponseResult.fail (e.getMessage ()); }en sonunda{ eğer (null! = ins) { Deneyin{ ins.close (); } catch (IOExceptione) { e.printStackTrace (); } } if (f.exists ()) {// Geçici dosyaları silin f.delete (); } } returnResponseResult.ok (anahtar); } publicstaticvoidinputStreamToFile (InputStreamins, Filefile) { Deneyin{ OutputStreamos = newFileOutputStream (dosya); intbytesRead = 0; bytebuffer = yeni bayt; while ((bytesRead = ins.read (arabellek, 0,8192))! = - 1) { os.write (arabellek, 0, bytesRead); } os.close (); ins.close (); } catch (Exceptione) { e.printStackTrace (); } } publicStringtxOssUpload (FileInputStreaminputStream, Stringkey, StringcontentType) { anahtar = Uuid.getUuid () + "-" + anahtar; OSSUtil.txOssUpload (inputStream, anahtar, contentType); Deneyin{ eğer (null! = inputStream) { inputStream.close (); } } catch (IOExceptione) { e.printStackTrace (); } Geri dönüş tuşu; } publicstaticvoidtxOssUpload (FileInputStreaminputStream, Stringkey, StringcontentType) { ObjectMetadataobjectMetadata = newObjectMetadata (); Deneyin{ intlength = inputStream.available (); objectMetadata.setContentLength (uzunluk); } catch (Exceptione) { logger.info (e.getMessage ()); } objectMetadata.setContentType (contentType); cosclient.putObject (txbucketName, key, inputStream, objectMetadata); }7. Dosyaları indirin
/ ** * Tencent Bulut Dosyası İndir * @ paramresponse * @ paramid *@dönüş * / @RequestMapping ("/ txOssDownload") publicObjecttxOssDownload (HttpServletResponseresponse, Stringid) { COSObjectInputStreamcosObjectInputStream = iFileStorageClient.txOssDownload (id, yanıt); StringcontentType = getContentType (id); FileUtil.txOssDownload (yanıt, contentType, cosObjectInputStream, id); returnnull; } publicstaticvoidtxOssDownload (HttpServletResponseresponse, StringcontentType, InputStreamfileStream, StringfileName) { FileOutputStreamfos = boş; response.reset (); OutputStreamos = boş; Deneyin{ response.setContentType (contentType + "; charset = utf-8"); eğer (! contentType.equals (PlConstans.FileContentType.image)) { Deneyin{ response.setHeader ("Content-Disposition", "attachment; filename =" + newString (fileName.getBytes ("UTF-8"), "ISO8859-1")); } catch (UnsupportedEncodingExceptione) { response.setHeader ("İçerik-Düzenleme", "ek; dosyaadı =" + dosyaAdı); logger.error ("kodlama dosyası başarısız", e); } } os = response.getOutputStream (); byteb = yeni bayt; intlen; while ((len = fileStream.read (b)) > 0) { os.write (b, 0, len); os.flush (); Deneyin{ eğer (fos! = null) { fos.write (b, 0, len); fos.flush (); } } catch (Exceptione) { logger.error (e.getMessage ()); } } } catch (IOExceptione) { IOUtils.closeQuietly (fos); fos = boş; }en sonunda{ IOUtils.closeQuietly (os); IOUtils.closeQuietly (fileStream); eğer (fos! = null) { IOUtils.closeQuietly (fos); } } }8. Ağ dosya akışını okuyun
/ ** * Ağ dosya akışını okuyun * @ paramurl *@dönüş * / publicstaticInputStreamreadFileFromURL (Stringurl) { if (StringUtils.isBlank (url)) { returnnull; } HttpClienthttpClient = newDefaultHttpClient (); HttpGetmethodGet = newHttpGet (url); Deneyin{ HttpResponseresponse = httpClient.execute (methodGet); eğer (response.getStatusLine (). getStatusCode () == 200) { HttpEntityentity = response.getEntity (); returnentity.getContent (); } } catch (Exceptione) { e.printStackTrace (); } returnnull; }9, ExcelUtil
/ ** * Excel'i okuyun * @ paraminputStream dosyası giriş akışı * @ iade listesi koleksiyonu * / publicstaticList < Nesne > oku (InputStreaminputStream) { returnEasyExcelFactory.read (inputStream, newSheet (1,1)); } / ** * Excel yaz * @ paramdatalist verileri * @ paramclazz * @ paramsaveFilePath dosyası kaydetme yolu * @ throwsIOException * / publicstaticvoidwrite (Liste < ? extendsBaseRowModel > veri, Sınıf < ? extendsBaseRowModel > clazz, StringsaveFilePath) throwsIOException { FiletempFile = newFile (saveFilePath); OutputStreamout = newFileOutputStream (tempFile); ExcelWriterwriter = EasyExcelFactory.getWriter (çıkış); Sheetsheet = newSheet (1,3, clazz, "Sheet1", null); writer.write (veri, sayfa); writer.finish (); out.close (); }Not: Bu noktada, tüm süreç tamamlanmıştır ve diğer bilgi noktası kodları da referans için aşağıda yayınlanmıştır.
1. @LoginRequired ek açıklama
/ ** * Giriş doğrulaması gerektiren Kontrolör yönteminde bu açıklamayı kullanın * / @Target ({ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) public @ interfaceLoginRequired { }2. MyControllerAdvice
@Hayalhanemersin publicclassMyControllerAdvice { @Kafadergisi @ExceptionHandler (TokenValidationException.class) publicJsonResponsetokenValidationExceptionHandler () { returnJsonResponse.loginInvalid (); } @Kafadergisi @ExceptionHandler (ServiceException.class) publicJsonResponseserviceExceptionHandler (ServiceExceptionse) { returnJsonResponse.fail (se.getMsg ()); } @Kafadergisi @ExceptionHandler (Exception.class) publicJsonResponseexceptionHandler (Exceptione) { e.printStackTrace (); returnJsonResponse.fail (e.getMessage ()); } }3. AuthenticationInterceptor
publicclassAuthenticationInterceptorimplementsHandlerInterceptor { privatestaticfinalStringCURRENT_USER = "kullanıcı"; @Autowired privateUserServiceuserService; @Override publicbooleanpreHandle (HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler) { // Yönteme doğrudan eşlenmemişse if (! (handlerinstanceofHandlerMethod)) { dönüş; } HandlerMethodhandlerMethod = (HandlerMethod) işleyici; Methodmethod = handlerMethod.getMethod (); // Arayüzde @LoginRequired ek açıklaması olup olmadığını belirleyin, varsa oturum açmanız gerekir LoginRequiredmethodAnnotation = method.getAnnotation (LoginRequired.class); if (methodAnnotation! = null) { // Jetonu doğrula IntegeruserId = JwtUtil.verifyToken (istek); PLUserplUser = userService.selectByPrimaryKey (userId); if (null == plUser) { thrownewRuntimeException ("Kullanıcı mevcut değil, lütfen tekrar oturum açın"); } request.setAttribute (CURRENT_USER, plUser); dönüş; } dönüş; } @Override publicvoidpostHandle (HttpServletRequesthttpServletRequest, HttpServletResponsehttpServletResponse, Objecto, ModelAndViewmodelAndView) throwsException { } @Override publicvoidafterCompletion (HttpServletRequesthttpServletRequest, HttpServletResponsehttpServletResponse, Objecto, Exceptione) throwsException { } }4. JwtUtil
publicstaticfinallongEXPIRATION_TIME = 2592_000_000L; // Geçerlilik süresi 30 gündür publicstaticfinalStringSECRET = "pl_token_secret"; publicstaticfinalStringHEADER = "belirteç"; publicstaticfinalStringUSER_ID = "kullanıcı kimliği"; / ** * Kullanıcı kimliğine göre belirteç oluşturun * @ paramuserId *@dönüş * / publicstaticStringgenerateToken (StringuserId) { HashMap < Dize, Nesne > map = newHashMap < > (); map.put (USER_ID, userId); Stringjwt = Jwts.builder () .setClaims (harita) .setExpiration (newDate (System.currentTimeMillis () + EXPIRATION_TIME)) .signWith (SignatureAlgorithm.HS512, SECRET) .kompakt(); returnjwt; } / ** * Jetonu doğrula * @ paramrequest * @ geri dönen userId tarafından doğrulandı * / publicstaticIntegerverifyToken (HttpServletRequestrequest) { Stringtoken = request.getHeader (HEADER); eğer (jeton! = null) { Deneyin{ Harita < Dize, Nesne > body = Jwts.parser () .setSigningKey (SECRET) .parseClaimsJws (jeton) .getBody (); for (Map.Entryentry: body.entrySet ()) { Objectkey = entry.getKey (); Objectvalue = entry.getValue (); eğer (key.toString (). equals (USER_ID)) { returnInteger.valueOf (value.toString ()); // userId } } returnnull; } catch (Exceptione) { logger.error (e.getMessage ()); thrownewTokenValidationException ("yetkisiz"); } }Başka{ thrownewTokenValidationException ("missingtoken"); } }