技術共有

vue3 springboot mybatis mysql プロジェクトの実践 - 簡単なログインおよび登録機能の実装

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

これは vue3+springboot+mybatis+mysql のプロジェクト実装です。これは、フロントエンドとバックエンドの分離のログインおよび登録機能を実装するだけです。主なツールは、idea、navicat です。

目次

1.vue3プロジェクトの作成と初期設定

vue3プロジェクトを作成する

2. プロジェクト構造を変更する

1) 元のディレクトリ構造

2) ディレクトリ構造の変更

ログイン登録ページの編集と書き込み

1)ログインと登録.vue

2)ホーム.vue

3)ルーター

4)ログイン.css

5) ログイン登録ページ表示

2. springboot+mysql+mybatisプロジェクトを作成し、データベースに接続します

3. ログインおよび登録のバックエンド関数を作成する

1. ログインロジック

2. 登録ロジック

3. バックエンドコード部分

4. プロジェクトを実行する


1.vue3プロジェクトの作成と初期設定

1.vue3プロジェクトを作成する

プロジェクトを作成するには、私の記事のいずれかを参照してください。

IDEA を使用してカスタム vue3 プロジェクトを作成する_idea vue3-CSDN ブログ

作成後の初期ディレクトリ構造:

2. プロジェクト構造を変更する

まず、元のディレクトリ構造を変更する必要があります

1) 元のディレクトリ構造

資産写真を投稿する

コンポーネント中間コンポーネント (通常は再利用可能)

ルーターすべてのメイン ページのファイル パスが設定されるルートです

通常、トークンの保存など、vuex の状態管理に使用されます。

ビュー中央がメインページです

アプリ.vueこれは、Vue アプリケーションのルート コンポーネントです。

メイン.jsこれはアプリケーションのエントリ ファイルであり、通常、vue や vue router などの依存関係を導入するために使用されます。

2) ディレクトリ構造の変更

ログインおよび登録機能を実装するために、変更されたディレクトリ構造は次のようになります。


3. ログイン登録ページを作成する

1)ログインと登録.vue

ログイン登録ページと機能を実装するために、Components フォルダーの下に LoginAndRegister.vue を作成します。ここでは、ログインと登録用の .vue ファイルのみを作成します。このファイルには、ログイン ブロックと登録ブロックの要素が含まれるかどうかを決定するために v-if が使用されます。 . レンダリングが行われるため、表示に影響を与えます。

初期設定

v-if="loginShow"为true, v-if="registerShow"为false

ボタンをクリックして切り替えると、true と false が切り替わります。

登録が成功したら、ログインセクションに戻ります。

利便性とユーザーの習慣のため、ユーザー属性には ID、ユーザー名、パスワード、電話番号、性別が含まれますが、登録時に入力されるのはユーザー名とパスワードのみであり、パスワードは暗号化されずに単純に機能が実装されます。安全性が十分ではありませんので、より安全なログインと登録方法、ログイン後の個人情報の改善方法について改めて記事を更新します。

ログインと登録.vue:

  1. <template>
  2. <div class="container">
  3. <div class="login-box" v-if="loginShow">
  4. <!-- 菱形群-->
  5. <div class="decoration1 decoration"></div>
  6. <div class="decoration2 decoration"></div>
  7. <div class="decoration3 decoration"></div>
  8. <div class="decoration4 decoration"></div>
  9. <div class="decoration5 decoration"></div>
  10. <div class="decoration decoration4 decoration6"></div>
  11. <div class="decoration decoration7 decoration2"></div>
  12. <div class="decoration decoration8 decoration3"></div>
  13. <div class="login-title">
  14. <h1>Login</h1>
  15. </div>
  16. <div class="login-part">
  17. <input class="login-input" v-model="username" placeholder="Username" />
  18. <input class="login-input" type="password" v-model="password" placeholder="Password" />
  19. <button class="login-button" @click="login">Login</button>
  20. <div>
  21. 还未注册?点击<a class="change-link" @click="changeToRegister">这里</a>注册
  22. </div>
  23. </div>
  24. </div>
  25. <div class="login-box" v-if="registerShow">
  26. <!-- 菱形群-->
  27. <div class="decoration1 decoration"></div>
  28. <div class="decoration2 decoration"></div>
  29. <div class="decoration3 decoration"></div>
  30. <div class="decoration4 decoration"></div>
  31. <div class="decoration5 decoration"></div>
  32. <div class="decoration decoration4 decoration6"></div>
  33. <div class="decoration decoration7 decoration2"></div>
  34. <div class="decoration decoration8 decoration3"></div>
  35. <div class="login-title">
  36. <h1>Register</h1>
  37. </div>
  38. <div class="login-part">
  39. <input class="login-input" v-model="username" placeholder="Username" />
  40. <input class="login-input" type="password" v-model="password" placeholder="Password" />
  41. <button class="login-button" @click="register">Register</button>
  42. <span class="change-link" @click="changeToLogin">返回登录</span>
  43. </div>
  44. </div>
  45. <!-- <div class="decoration decoration1"></div>-->
  46. <!-- <div class="decoration decoration2"></div>-->
  47. <!-- <div class="decoration decoration3"></div>-->
  48. <!-- <div class="decoration decoration4"></div>-->
  49. </div>
  50. </template>
  51. <script>
  52. import { ref } from 'vue'
  53. import { useRouter } from 'vue-router' // 导入 useRouter
  54. import '../style/Login.css' // 导入css
  55. export default {
  56. name: 'LoginVue',
  57. setup () {
  58. const username = ref('')
  59. const password = ref('')
  60. const phone = ref('')
  61. const loginShow = ref(true)
  62. const registerShow = ref(false)
  63. const router = useRouter()
  64. const changeToRegister = async () => {
  65. loginShow.value = false
  66. registerShow.value = true
  67. }
  68. const changeToLogin = async () => {
  69. loginShow.value = true
  70. registerShow.value = false
  71. }
  72. const login = async () => {
  73. console.log('Login with:', username.value, password.value)
  74. try {
  75. const formData = new FormData()
  76. formData.append('username', username.value)
  77. formData.append('password', password.value)
  78. const response = await fetch('http://localhost:8081/api/user/login', {
  79. method: 'POST',
  80. body: formData
  81. })
  82. const data = await response.json()
  83. if (response.ok) {
  84. console.log('Link success', data)
  85. if (data.code === 200) {
  86. // 登录成功
  87. alert('登录成功!')
  88. await router.push('/home')
  89. } else {
  90. alert(data.msg)
  91. }
  92. } else {
  93. console.error('Link failed', data)
  94. }
  95. } catch (error) {
  96. console.error('Error login', error)
  97. }
  98. }
  99. const register = async () => {
  100. console.log('Register with:', username.value, password.value)
  101. try {
  102. const formData = new FormData()
  103. formData.append('username', username.value)
  104. formData.append('password', password.value)
  105. const response = await fetch('http://localhost:8081/api/user/register', {
  106. method: 'POST',
  107. body: formData
  108. })
  109. const data = await response.json()
  110. if (response.ok) {
  111. if (data.code === 200) {
  112. console.log('Register success', data)
  113. alert('注册成功!')
  114. await changeToLogin()
  115. } else {
  116. console.log('Register failed', data)
  117. alert(data.msg)
  118. }
  119. } else {
  120. console.error('Register failed', data)
  121. }
  122. } catch (error) {
  123. console.error('Error during register', error)
  124. }
  125. }
  126. return { username, password, phone, login, loginShow, registerShow, changeToRegister, register, changeToLogin }
  127. }
  128. }
  129. </script>
  130. <style>
  131. </style>

2)ホーム.vue

Home.vue は、ログインに成功した後にジャンプするメイン ページです。

ホーム.vue:

  1. <template>
  2. 首页<br><br>
  3. <button class="login-button" @click="signOut">退出登录</button>
  4. </template>
  5. <script>
  6. import { useRouter } from 'vue-router'
  7. export default {
  8. name: 'HomeVue',
  9. setup () {
  10. const router = useRouter()
  11. const signOut = async () => {
  12. await router.push('/')
  13. }
  14. return { signOut }
  15. }
  16. }
  17. </script>
  18. <style scoped>
  19. </style>

3)ルーター

ページ ルーティング設定。パスが /、/login がログイン ページ、/home がホームページの場合、ログイン ページにリダイレクトされます。

index.js:

  1. import { createRouter, createWebHistory } from 'vue-router'
  2. import Login from '../components/LoginAndRegister.vue'
  3. import Home from '../views/Home.vue'
  4. const routes = [
  5. {
  6. path: '/',
  7. redirect: '/login'
  8. },
  9. {
  10. path: '/login',
  11. name: 'Login',
  12. component: Login
  13. },
  14. {
  15. path: '/home',
  16. name: 'Home',
  17. component: Home
  18. }
  19. ]
  20. const router = createRouter({
  21. history: createWebHistory(process.env.BASE_URL),
  22. routes
  23. })
  24. export default router

4)ログイン.css

ログイン登録ページのCSSデザインです。

ログイン.css:

  1. *{
  2. margin: 0;
  3. padding: 0;
  4. }
  5. .container{
  6. height: 100vh;
  7. display: flex;
  8. justify-content: center;
  9. align-items: center;
  10. overflow: hidden;
  11. position: relative;
  12. }
  13. .login-box{
  14. background-color: white;
  15. padding: 40px 100px;
  16. border-radius: 8px;
  17. box-shadow: 0 0 5px 1px gainsboro;
  18. position: relative;
  19. }
  20. .login-part{
  21. display: flex;
  22. flex-direction: column;
  23. justify-content: center;
  24. margin-top: 20px;
  25. gap: 20px;
  26. }
  27. .login-input{
  28. width: 250px;
  29. height: 30px;
  30. border-radius: 8px;
  31. }
  32. .login-button{
  33. height: 40px;
  34. border-radius: 8px;
  35. background-color: #2c3e50;
  36. color: white;
  37. transition: 0.5s;
  38. }
  39. .login-button:hover{
  40. background-color: darkcyan;
  41. font-size: 15px;
  42. transition: 0.5s;
  43. }
  44. .login-button:active{
  45. background-color: darkslateblue;
  46. }
  47. .change-link{
  48. color: #00BFFF;
  49. text-decoration: underline;
  50. }
  51. .change-link:hover{
  52. color: cornflowerblue;
  53. }
  54. .decoration {
  55. position: absolute;
  56. width: 200px;
  57. height: 200px;
  58. background: linear-gradient(to left, #FDF5E6, #96CDCD );
  59. clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  60. z-index: 1;
  61. }
  62. .decoration1 {
  63. top: 150px;
  64. left: -210px;
  65. }
  66. .decoration2 {
  67. top: 20px;
  68. right: -20px;
  69. width: 100px; /* 第二个菱形的大小 */
  70. height: 100px;
  71. background: linear-gradient(to right, #FFF5EE, #E6E6FA);
  72. }
  73. .decoration3 {
  74. top: 50px;
  75. right: -180px;
  76. width: 200px; /* 第三个菱形的大小 */
  77. height: 200px;
  78. background: linear-gradient(to right, #7FFFD4, cadetblue);
  79. }
  80. .decoration4 {
  81. top: 200px;
  82. right: -200px;
  83. width: 500px; /* 第三个菱形的大小 */
  84. height: 500px;
  85. z-index: -1;
  86. clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  87. background: linear-gradient(to right, #FFFACD, #00BFFF);
  88. }
  89. .decoration5 {
  90. top: -100px;
  91. right: 200px;
  92. width: 400px; /* 第三个菱形的大小 */
  93. height: 400px;
  94. z-index: -1;
  95. clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  96. background: linear-gradient(to right, #AFEEEE, #00BFFF);
  97. }
  98. .decoration6 {
  99. top: 10px;
  100. right: -680px;
  101. }
  102. .decoration7 {
  103. top: -170px;
  104. right: -500px;
  105. }
  106. .decoration8 {
  107. top: -140px;
  108. right: -655px;
  109. }

5) ログイン登録ページ表示

ひし形のブロックはランダムに配置されており、最初は次のようになります。

その後、さらにいくつかのひし形のブロックを追加し、その位置と色を変更しました。最終的な効果は次のとおりです。

2. springboot+mysql+mybatisプロジェクトを作成し、データベースに接続します

springboot、mysql、mybatis を使用してバックエンド プロジェクトを構築し、データベースに接続するだけです。参照:

アイデア、Spring Boot+MySQL+MyBatis プロジェクトがデータベース テーブルの内容を Web ページに作成して表示する_idea が Web ページにデータベースを表示する - CSDN ブログ

記事の補足:

エンティティ クラスを作成するたびに set メソッドと get メソッドを記述するのが面倒な場合は、pom.xml に次の依存関係を追加できます。

  1. <dependency>
  2. <groupId>org.projectlombok</groupId>
  3. <artifactId>lombok</artifactId>
  4. </dependency>

次に、エンティティ クラスで @Data アノテーションを使用して、set メソッドと get メソッドの記述を省略します。

プロセスはほぼ同じですが、今回作成したデータは異なります。主な理由は、ユーザー テーブルの属性とデータが変更されたことです (違いは大きくなく、スープは薬を変更しません)。

問題が発生しました: Maven は依存関係のダウンロードを続けますが、長時間応答がありません

ただし、今回は、新しいコンピューターを使用してバックエンド プロジェクトを作成しました。その結果、Maven が起動された後、さまざまな依存関係とプラグインがダウンロードされ続けました。 -ins、そして長い間応答がありませんでした:

解決:

キャッシュをクリアしてアイデアを再起動しましたが、効果はほとんどありませんでした。

後で、Maven がデフォルトで外部の中央ウェアハウスを使用し、アイデアで Maven プラグインを使用していたため、ダウンロード速度が非常に遅くなったことが原因である可能性があることがわかりました。

そこで、mavenをローカルにダウンロードしました。チュートリアルを参照してください。

Maven のダウンロードとインストールのチュートリアル (超詳細)_Maven のインストール - CSDN ブログ

チュートリアルに従ってダウンロードし、Mavenのインストールパス-&gt;conf-&gt;settings.xmlにあるイメージのURLを変更します。ただし、環境変数は設定せず、file-&gt;settings-&gt;で直接設定しました。 [ビルド、実行、デプロイ] -&gt; [ビルド ツール] -&gt; Maven で、Maven ホーム パスをローカル パスに変更します。

変更後、ダウンロード速度は確かに大幅に速くなりました。

最終的なバックエンド プロジェクトのディレクトリ構造は次のとおりです。

3. ログインおよび登録のバックエンド関数を作成する

1. ログインロジック

フロントエンドから渡されたユーザー名とパスワードを含む入力情報を取得し、データベース内のユーザー名とパスワードに基づいてクエリを実行します。ユーザーが見つかった場合は、そのユーザーが存在し、ユーザー名とパスワードが一致していることを意味します。ログインは成功しますが、それ以外の場合は失敗します。

2. 登録ロジック

フロントエンドから渡されたユーザー名とパスワードを含む入力情報を取得します。入力情報が空でないことを確認した後、まずユーザー名に従ってデータベースを検索します。見つかった場合は、そのユーザー名が登録されています。失敗し、失敗情報が返されます。登録が成功すると、ユーザーはレコードを登録してデータベースに挿入できます。ログイン ブロックは表示され、登録ブロックは非表示になります。

3. バックエンドコード部分

その中で、リソース -&gt; マッパー -&gt; UserMapper.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  4. <mapper namespace="com.example.demo.mapper.UserMapper" >
  5. <resultMap id="result" type="com.example.demo.entity.User">
  6. <result property="id" column="id" />
  7. <result property="username" column="username" />
  8. <result property="password" column="password" />
  9. <result property="phone" column="phone" />
  10. <result property="gender" column="gender"/>
  11. </resultMap>
  12. <!-- 通过用户名和密码查找对应用户,用于登录-->
  13. <select id="findUserByNameAndPwd" resultMap="result" parameterType="User">
  14. select * from user
  15. where username = #{username}
  16. and password = #{password}
  17. </select>
  18. <!-- 通过用户名查找对应用户,用于注册检验用户名是否已存在-->
  19. <select id="findUserByName" resultMap="result" parameterType="User">
  20. select * from user
  21. where username = #{username}
  22. </select>
  23. <!-- 添加用户-->
  24. <insert id="addUser" parameterType="User">
  25. insert into user (username, password)
  26. values ( #{username}, #{password} )
  27. </insert>
  28. </mapper>

java-&gt;com.example.demo-&gt;mapper-&gt;UserMapper.java:

  1. package com.example.demo.mapper;
  2. import com.example.demo.entity.User;
  3. import org.apache.ibatis.annotations.Mapper;
  4. @Mapper
  5. public interface UserMapper {
  6. // 通过用户名和密码查找对应用户
  7. public User findUserByNameAndPwd(User user);
  8. // 通过用户名查找用户
  9. public User findUserByName(User user);
  10. // 添加用户
  11. public void addUser(User user);
  12. }

java-&gt;com.example.demo-&gt;service-&gt;UserService.java:

  1. package com.example.demo.service;
  2. import com.example.demo.entity.User;
  3. public interface UserService {
  4. // 通过用户名和密码查找对应id
  5. public User findUserByNameAndPwd(User user);
  6. // 通过用户名查找用户
  7. public User findUserByName(User user);
  8. // 添加用户
  9. public void addUser(User user);
  10. }

java-&gt;com.example.demo-&gt;service-&gt;UserServiceImpl.java:

  1. package com.example.demo.service;
  2. import com.example.demo.entity.User;
  3. import com.example.demo.mapper.UserMapper;
  4. import jakarta.annotation.Resource;
  5. import org.springframework.stereotype.Service;
  6. @Service
  7. public class UserServiceImpl implements UserService {
  8. @Resource
  9. private UserMapper userMapper;
  10. // 通过用户名和密码查找对应id
  11. @Resource
  12. public User findUserByNameAndPwd(User user){
  13. return userMapper.findUserByNameAndPwd(user);
  14. }
  15. // 通过用户名查找用户
  16. @Resource
  17. public User findUserByName(User user){
  18. return userMapper.findUserByName(user);
  19. }
  20. // 添加用户
  21. @Resource
  22. public void addUser(User user){
  23. userMapper.addUser(user);
  24. }
  25. }

java-&gt;com.example.demo-&gt;コントローラ-&gt;UserController.java:

  1. package com.example.demo.controller;
  2. import com.example.demo.entity.User;
  3. import com.example.demo.result.Result;
  4. import com.example.demo.service.UserService;
  5. import jakarta.annotation.Resource;
  6. import org.springframework.web.bind.annotation.*;
  7. @RestController
  8. @RequestMapping("/api/user")
  9. public class UserController {
  10. @Resource
  11. UserService userService;
  12. // 登录
  13. @CrossOrigin
  14. @PostMapping(value = "/login")
  15. public Result login(@ModelAttribute("user") User user){
  16. String username=user.getUsername();
  17. String password=user.getPassword();
  18. System.out.println("Login received username: " + username);
  19. System.out.println("Login received password: " + password);
  20. User userCheck = new User();
  21. userCheck.setUsername(username);
  22. userCheck.setPassword(password);
  23. System.out.println(userCheck.getUsername() + " " + userCheck.getPassword());
  24. try{
  25. User findUser = userService.findUserByNameAndPwd(userCheck);
  26. if(findUser != null){
  27. return Result.success(findUser);
  28. }else {
  29. return Result.failure(401,"用户名或密码错误");
  30. }
  31. }catch (Exception e){
  32. return Result.failure(500,"服务器异常");
  33. }
  34. }
  35. // 注册
  36. @CrossOrigin
  37. @PostMapping(value = "/register")
  38. public Result register(@ModelAttribute("user") User user){
  39. // String username = "222";
  40. // String password = "222";
  41. User userCheck = new User();
  42. userCheck.setUsername(user.getUsername());
  43. userCheck.setPassword(user.getPassword());
  44. if(userCheck.getUsername() == null || userCheck.getUsername().isEmpty() || userCheck.getPassword() == null || userCheck.getPassword().isEmpty()){
  45. System.out.println("用户名或密码不可为空");
  46. return Result.failure(201,"用户名和密码不可为空");
  47. }else {
  48. System.out.println("Register received username: " + userCheck.getUsername());
  49. System.out.println("Register received password: " + userCheck.getPassword());
  50. try{
  51. // 先在数据库中查找是否已有用户名相同的用户
  52. User findUser = userService.findUserByName(userCheck);
  53. if(findUser != null){
  54. // 用户名已存在
  55. return Result.failure(202,"用户名已存在!");
  56. }
  57. else {
  58. // 新用户,数据库添加记录
  59. userService.addUser(userCheck);
  60. return Result.success(userCheck);
  61. }
  62. }catch (Exception e) {
  63. return Result.failure(500, "服务器异常");
  64. // }
  65. }
  66. }
  67. }
  68. }

4. プロジェクトを実行する

フロントエンドとバックエンドは別々に実行および開始されます。ここでは、application.properties でバックエンドのポートを 8081 に変更し、フロントエンドはデフォルトの 8080 です。そのため、フロントエンドとバックエンドのプロジェクトが正常に実行されたら、http:/ と入力します。ブラウザーで /localhost:8080 を確認し、開発者ツールのネットワークで確認し、バックエンドに正常に接続し、ログインしてテスト入力を登録するときに別のプロンプト情報とポップアップ プロンプトを正常に返します。

ログインに成功した後: