Ես իրականացնում եմ բեռնման գործառույթ՝ օգտագործելով Grails, որտեղ հիմնականում օգտվողը կարող է վերբեռնել տեքստային ֆայլ, այնուհետև համակարգը կպահպանի այդ տեքստային ֆայլի յուրաքանչյուր տողը որպես տվյալների բազայի գրառում: Թեև բեռնումը լավ է աշխատում, ավելի մեծ ֆայլերը մշակելու համար ժամանակ է պահանջվում, և, հետևաբար, նրանք խնդրում են ունենալ առաջընթացի սանդղակ, որպեսզի օգտվողները կարողանան որոշել՝ արդյոք իրենց վերբեռնումը դեռ մշակվում է, թե իրական սխալ է տեղի ունեցել:
Դա անելու համար ես արեցի երկու URL-ի ստեղծում.
/upload
որը փաստացի URL-ն է, որը ստանում է վերբեռնված տեքստային ֆայլը:/upload/status?uploadToken=
, որն իրuploadToken
-ի հիման վրա վերադարձնում է որոշակի վերբեռնման կարգավիճակ:
Այն, ինչ ես արեցի, այն է, որ յուրաքանչյուր տող մշակելուց հետո ծառայությունը կթարմացնի նստաշրջանի մակարդակի հաշվիչի փոփոխականը.
// import ...
class UploadService {
Map upload(CommonsMultipartFile record, GrailsParameterMap params) {
Map response = [success: true]
try {
File file = new File(record.getOriginalFilename())
FileUtils.writeByteArrayToFile(file, record.getBytes())
HttpSession session = WebUtils.retrieveGrailsWebRequest().session
List<String> lines = FileUtils.readLines(file, "UTF-8"), errors = []
String uploadToken = params.uploadToken
session.status.put(uploadToken,
[message: "Checking content of the file of errors.",
size: lines.size(),
done: 0])
lines.eachWithIndex { l, li ->
// ... regex checking per line and appending any error to the errors List
session.status.get(uploadToken).done++
}
if(errors.size() == 0) {
session.status.put(uploadToken,
[message: "Persisting record to the database.",
size: lines.size(),
done: 0])
lines.eachWithIndex { l, li ->
// ... Performs GORM manipulation here
session.status.get(uploadToken).done++
}
}
else {
response.success = false
}
}
catch(Exception e) {
response.success = false
}
response << [errors: errors]
return response
}
}
Այնուհետև ստեղծեք պարզ WebSocket իրականացում, որը միանում է /upload/status?uploadToken=
URL-ը: Խնդիրն այն է, որ ես չեմ կարող մուտք գործել նիստի փոփոխական POGO-ներում: Ես նույնիսկ փոխում եմ այդ POGO-ն Grails ծառայության, քանի որ կարծում էի, որ դա է խնդրի պատճառը, բայց ես դեռ չեմ կարող մուտք գործել նիստի փոփոխական:
// import ...
@ServerEndpoint("/upload/status")
@WebListener
class UploadEndpointService implements ServletContextListener {
@OnOpen
public void onOpen(Session userSession) { /* ... */ }
@OnClose
public void onClose(Session userSession, CloseReason closeReason) { /* ... */ }
@OnError
public void onError(Throwable t) { /* ... */ }
@OnMessage
public void onMessage(String token, Session userSession) {
// Both of these cause IllegalStateException
def session = WebUtils.retrieveGrailsWebRequest().session
def session = RequestContextHolder.currentRequestAttributes().getSession()
// This returns the session id but I don't know what to do with that information.
String sessionId = userSession.getHttpSessionId()
// Sends the upload status through this line
sendMessage((session.get(token) as JSON).toString(), userSession)
}
private void sendMessage(String message, Session userSession = null) {
Iterator<Session> iterator = users.iterator()
while(iterator.hasNext()) {
iterator.next().basicRemote.sendText(message)
}
}
}
Եվ փոխարենը, ինձ սխալ է տալիս.
Պատճառված է IllegalStateException. Շղթայական կապով հարցում չի գտնվել. Դուք նկատի ունեք ատրիբուտների հարցումը իրական վեբ հարցումից դուրս, թե՞ հարցումն եք մշակում սկզբնապես ստացվող շղթայից դուրս: Եթե դուք իրականում աշխատում եք վեբ հարցման շրջանակներում և դեռ ստանում եք այս հաղորդագրությունը, ձեր կոդը, հավանաբար, աշխատում է DispatcherServlet/DispatcherPortlet-ից դուրս: Այս դեպքում օգտագործեք RequestContextListener կամ RequestContextFilter՝ ընթացիկ հարցումը բացահայտելու համար:
Ես արդեն հաստատել եմ, որ վեբ վարդակն աշխատում է՝ ստիպելով այն ուղարկել ստատիկ String
բովանդակություն: Բայց այն, ինչ ես ուզում եմ, այն է, որ կարողանամ ստանալ այդ հաշվիչը և սահմանել այն որպես ուղարկելու հաղորդագրություն: Ես օգտագործում եմ Grails 2.4.4-ը և Grails Spring Websocket հավելվածը, թեև խոստումնալից է թվում, հասանելի է միայն Grails 3-ից սկսած: Կա՞ արդյոք դրան հասնելու որևէ միջոց, կամ եթե ոչ, ի՞նչ մոտեցում պետք է օգտագործեմ: