我正在嘗試將我的react.jsocks客戶端連接到我的spring boot後端Web套接字,但我無法連接它們,它在chrome控制台上給了我一些錯誤,如下所示:
chrome 控制台錯誤
我的 Spring Boot 部分沒有任何錯誤,但有一些類似的警告:
彈簧啟動控制台
為什麼我無法連接它們我的react.js部分是這樣的:
import background from'../Styles/Background.module.css' import formdesign from'../Styles/FormDesign.module.css' import Bounce from 'react-reveal/Bounce'; import cookies from 'js-cookie' import Menustyle from'../Styles/Menu.module.css' import {useLocation, useNavigate} from 'react-router-dom'; import { useState ,useEffect } from 'react'; import swal from 'sweetalert'; import Swal from 'sweetalert2' import { connect } from 'react-redux'; import { Oval } from 'react-loader-spinner'; import {GetWithAuth ,GetWithRefresh,beforeRegister,registerWithMail, beforeLogin} from '../Services/HttpServices'; import { isUserBlockExist } from '../Services/UserPrefs'; import SockJS from 'sockjs-client'; import { over } from 'stompjs'; let number = 1; const Login = (props)=>{ const navigate = useNavigate(); const location = useLocation(); const [isLoading, setIsLoading] = useState(true); const [allState,setAllState] = useState({ title:props.title, message:props.message, button:props.button, show:true }); const beforeLoad = async ()=>{ let sock = new SockJS(`${process.env.REACT_APP_ROOT_URL}/wss`); let stompClient = over(sock); stompClient.connect({},function(frame){ console.log("Connected : "+frame); //stompClient.subscribe("/user-connect/user",this.onPrivateMessage); }); try{ console.log(process.env.REACT_APP_ROOT_URL); let response = await GetWithAuth(`${process.env.REACT_APP_ROOT_URL}/auth/route`,"/homepage",props.jwtsession); if(response.route == "/"){ document.body.className = background.deneme; props.setJwtSession(""); //localStorage.removeItem("jwtsession"); } else{ document.body.className = Menustyle.deneme; } setIsLoading(false); navigate(response.route); } catch{ window.location.reload(); } } const handleClick = ()=>{ if(allState.show === false && number === 1){ setAllState({show:true,message:"Have Account ?",title:"Sign-Up"}); } else if(allState.show === false && number === 2){ setAllState({show:true,message:"Don't Have Account ?",title:"Login"}); } } const submit = async()=>{ if(document.getElementById("password").value.trim().length ==0){ swal({ title: "Password Field Is Required!", text: "Please Write Your Password", icon: "error", button: "Close This Alert", }); } else if(document.getElementById("username").value.trim().length ==0){ swal({ title: "Username Field Is Required!", text: "Please Write Your Username", icon: "error", button: "Close This Alert", }); } else if(document.getElementById("username").value.trim().length >=15&&allState.title!="Login"){ swal({ title: "Username Can Not More Than 15 Characters", text: "Please Try Another Username", icon: "error", button: "Close This Alert", }); } else if(document.getElementById("email")!=null && document.getElementById("email").value.trim().length ==0){ swal({ title: "E-Mail Field Is Required!", text: "Please Write Your E-Mail", icon: "error", button: "Close This Alert", }); } else if(allState.title === "Sign-Up"){ let postres = await beforeRegister(`${process.env.REACT_APP_ROOT_URL}/auth/beforeregister`,document.getElementById("username").value.trim(),document.getElementById("email").value,document.getElementById("password").value); if(postres.created == true){ Swal.fire({ html:`<h1>Please Write The Code We Sent To Your Email</h1> <input type="text" id="code" class="swal2-input" placeholder="CODE" style="width:50%;"> <button id="send" class="btn btn-success"> SEND </button><br/><br/> You Have <strong></strong> seconds.<br/><br/> `, timer:90000, icon: "success", allowOutsideClick:false, showCancelButton:true, didOpen: ()=>{ const content = Swal.getHtmlContainer() const $ = content.querySelector.bind(content) const send = $('#send'); const code = $('#code'); send.addEventListener("click",async()=>{ let postres2 = await registerWithMail(`${process.env.REACT_APP_ROOT_URL}/auth/registerwithmail`,code.value.trim().toLowerCase()); if(postres2.created == true){ props.setJwtSession(postres2.accessToken); //localStorage.setItem("jwtsession",postres2.accessToken); navigate('/homepage'); Swal.close(); } else if(postres2.created == false){ Swal.close(); swal({ title: postres2.error, text: "Please Check And Try Again", icon: "error", button: "Close This Alert", }); } }); Swal.showLoading(); setInterval(() => { Swal.getHtmlContainer().querySelector('strong') .textContent = (Swal.getTimerLeft() / 1000) .toFixed(0) }, 100) }}) } else{ swal({ title: postres.error, text: "Please Check And Try Again", icon: "error", button: "Close This Alert", }); } } else if(allState.title === "Login"){ let postres = await beforeLogin(`${process.env.REACT_APP_ROOT_URL}/auth/beforelogin`,document.getElementById("username").value.trim(),document.getElementById("password").value); if(postres.created == true){ Swal.fire({ html:`<h1>Please Write The Code We Sent To Your Email</h1> <input type="text" id="code" class="swal2-input" placeholder="CODE" style="width:90%; margin-left:0px;"> <button id="send" class="btn btn-success"> SEND </button> <button id="close" class="btn btn-secondary"> CLOSE </button><br/><br/> You Have <strong></strong> seconds.<br/><br/> `, timer:90000, icon: "success", allowOutsideClick:false, didOpen: ()=>{ const content = Swal.getHtmlContainer() const $ = content.querySelector.bind(content) const send = $('#send'); const code = $('#code'); send.addEventListener("click",async()=>{ let postres2 = await registerWithMail(`${process.env.REACT_APP_ROOT_URL}/auth/loginwithmail`,code.value.trim().toLowerCase()); if(postres2.created == true){ props.setJwtSession(postres.accessToken.toString()); console.log(postres.accessToken); navigate('/homepage'); Swal.close(); } else if(postres2.created == false){ Swal.close(); swal({ title: postres2.error, text: "Please Check And Try Again", icon: "error", button: "Close This Alert", }); } }); Swal.showLoading(); setInterval(() => { Swal.getHtmlContainer().querySelector('strong') .textContent = (Swal.getTimerLeft() / 1000) .toFixed(0) }, 100) }}) } else if(postres.created === false && postres.blocked == false){ swal({ title: postres.error, text: "Please Check And Try Again", icon: "error", button: "Close This Alert", }); console.log(postres); } else{ swal({ title: postres.error, text: "Please Check And Try Again", icon: "error", button: "Close This Alert", }); } } } useEffect(() =>{ beforeLoad(); },[]); useEffect( ()=>{ setTimeout(() => { if(allState.show === true && number === 1){ setAllState({show:false,message:"Have Account ?",title:"Sign-Up"}); number = 2; console.log(allState.message); } else if(allState.show === true && number === 2){ setAllState({show:false,message:"Don't Have Account ?",title:"Login"}); number = 1; } }, 300); },[allState]); if (isLoading) { return <div className={formdesign.loading}> <Oval width="100" height="100" color="black" ariaLabel='loading' /> </div>; } return( <div> <Bounce left opposite when={!allState.show}> <div className={allState.title =="Login" ? formdesign.formBack : formdesign.formBackSignUp}> <h1 className={formdesign.Title}>{allState.title}</h1> <input type="text" name = "username" placeholder={allState.title == 'Login' ? 'Username Or Email' : 'Username'} id='username'></input> {allState.title =="Sign-Up" && <input type="text" name = "email" placeholder="E-Mail" id='email'></input> } <input type="password" name = "password" placeholder="Password" id='password'></input> <input type="button" value={allState.title} onClick = {submit} ></input> <p>{allState.message} <span style={{color:"blue",cursor:"pointer"}} onClick = {handleClick}>Click Here</span></p> </div> </Bounce> </div> );} const mapStateToProps = (state)=>{ return{ jwtsession:state.jwtsession } } const mapDispatchToProps = (dispatch) =>{ return{ setJwtSession: (jwtsession) =>{ dispatch({'type':'SET_JWTSESSION',jwtsession})} } } export default connect(mapStateToProps,mapDispatchToProps) (Login);
和我的 Spring Boot 設定類別:
package com.project.blog.websocket; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer { @Value("${blog.app.front}") private String url; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/wss").setAllowedOrigins(url).setAllowedOriginPatterns("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.setApplicationDestinationPrefixes("/app"); registry.enableSimpleBroker("/user-connect"); registry.setUserDestinationPrefix("/user"); } }
同樣對於網路套接字控制器我寫了這部分:
package com.project.blog.websocket; import com.project.blog.entities.User; import com.project.blog.repositories.UserRepository; import com.project.blog.responses.ErrorSuccessResponse; import lombok.RequiredArgsConstructor; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Controller; import java.time.LocalDateTime; import java.util.LinkedList; import java.util.List; @Controller @RequiredArgsConstructor public class WebSocketController { private final SimpMessagingTemplate simpMessagingTemplate; private final UserRepository userRepository; @MessageMapping("/message") private ErrorSuccessResponse receiveMessage(String user){ ErrorSuccessResponse errorSuccessResponse = new ErrorSuccessResponse(); errorSuccessResponse.setError("block oldu"); simpMessagingTemplate.convertAndSendToUser(user,"/private",errorSuccessResponse); return errorSuccessResponse; } @Scheduled(fixedDelay = 1000) private void checkBlocks(){ LocalDateTime now = LocalDateTime.now(); List<User> users = userRepository.findBlockedUsers(now); users.stream().forEach(user->{ receiveMessage(user.getUsername()); }); } }
我嘗試使用襪子連接我的react.js前端和spring boot後端,但我做不到
我的 process.env.REACT_APP_ROOT_URL 是:http://localhost:1998 和@Value(“${blog.app.front}”) 私有字串 url;這部分值是:http://localhost:3000
P粉7594512552024-03-27 13:24:23
問題可能出在客戶端或伺服器端。第一步是能夠使用測試工具單獨測試伺服器。這並不容易,因為程式碼在 SockJS 上使用 STOMP 協定。
您可能不需要使用 SockJS。請參閱將 STOMP 與 SockJS 結合使用。所以第一步是刪除 SockJS 的使用,看看它是否有效。
下一步是取消 STOMP 的使用。一種更簡單的方法是僅使用純文字訊息。如果您這樣做,則可以使用命令列工具,例如 wscat 或 Chrome 瀏覽器外掛程式例如 WebSocketKing 來自行測試伺服器。一旦伺服器與測試工具一起工作,您就可以使用客戶端程式碼進行測試。
我遇到了類似的問題,最終使用 JSON 訊息開發了自己的協議,以 WebSocket 文字訊息的形式發送。我可以使用 WebSocket King 單獨測試伺服器。捲動到 Brill Middleware 的末尾查看使用 WebSocket King 的範例。