【JAVA应用实战-SpringBoot】(七)SpringBoot实现用户登录退出+查看新闻CURD

一、组件版本

1)java 1.8.0_451
2)springboot 2.7.18
3)pagehelper-spring-boot-starter 1.4.5
4)mysql-connector-java

二、实现功能

1)实现需要登录才能查看其他页面
2)实现界面的增删改查
3)mybatis支持sql写mapper文件和xml文件两种方式
4)pagehelper实现分页功能

三、代码实现

1、代码架构

2、pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springboot-login-news-curd</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- SpringBoot Web 模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>

        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>

        <!-- Thymeleaf for Frontend -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- PageHelper分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.5</version> <!-- 请根据需要选择合适的版本 -->
        </dependency>

    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName><!--修改编译出来的jar包名,仅为{artifactId}.jar-->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <descriptorRefs>
                        <!--给jar包起的别名-->
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>org.example.MyApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

3、控制器层

controller/UserController.java
package org.example.controller;

import org.example.pojo.User;
import org.example.service.UserService;
import org.example.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/login")
    public String login() {
        return "user/login"; // 返回登录页面
    }

    @PostMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        RedirectAttributes redirectAttributes) {
        User user = userService.getUserByUsername(username);
        if (user != null && user.getPassword().equals(password)) {
            // 登录成功,将用户信息存入会话
            SecurityUtil.setLoginUser(user);
            return "redirect:/news/"; // 跳转到新闻页面
        } else {
            // 登录失败,返回登录页面并提示错误
            redirectAttributes.addFlashAttribute("error", "用户名或密码错误");
            return "redirect:/user/login";
        }
    }

    @GetMapping("/logout")
    public String logout() {
        // 登出,清除会话中的用户信息
        SecurityUtil.removeLoginUser();
        return "redirect:/user/login"; // 跳转到登录页面
    }
}

controller/NewsController.java

package org.example.controller;


import org.example.pojo.News;
import org.example.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Controller
@RequestMapping("/news")
public class NewsController {
    @Autowired
    private NewsService newsService;

    @GetMapping("/")
    public String list(Model model) {
        List<News> newsList = newsService.getAllNews();
        model.addAttribute("newsList", newsList);
        return "news/list";
    }

    @GetMapping("/add")
    public String add(Model model) {
        model.addAttribute("news", new News());
        return "news/add";
    }

    @PostMapping("/save")
    public String save(@ModelAttribute News news) {
        newsService.saveNews(news);
        return "redirect:/news/";
    }

    @GetMapping("/edit/{id}")
    public String edit(@PathVariable Integer id, Model model) {
        News news = newsService.getNewsById(id);
        model.addAttribute("news", news);
        return "news/edit";
    }

    @PostMapping("/update")
    public String update(@ModelAttribute News news) {
        newsService.updateNews(news);
        return "redirect:/news/";
    }

    @GetMapping("/delete/{id}")
    public String delete(@PathVariable Integer id) {
        newsService.deleteNews(id);
        return "redirect:/news/";
    }
}

4、config层

config/MyBatisConfig.java
package org.example.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

@Configuration
@MapperScan("org.example.mapper")
public class MyBatisConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
//        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
//                .getResources("classpath:mapper/*.xml"));
        return sessionFactory.getObject();
    }
}

5、拦截器层

interceptor/LoginInterceptor.java
package org.example.interceptor;

import org.example.util.SecurityUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查用户是否已经登录
        if (!SecurityUtil.isLogin()) {
            // 如果未登录,重定向到登录页面
            response.sendRedirect(request.getContextPath() + "/user/login");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 无需实现
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 无需实现
    }
}

6、mapper层

mapper/NewsMapper.java

package org.example.mapper;


import org.apache.ibatis.annotations.*;
import org.example.pojo.News;

import java.util.List;

/**
 * 文章Mapper - sql都写在 mapper 文件中
 */
public interface NewsMapper {
    @Select("SELECT * FROM news")
    List<News> findAll();

    @Select("SELECT * FROM news WHERE id = #{id}")
    News findById(@Param("id") Integer id);

    @Insert("INSERT INTO news (title, content) VALUES (#{title}, #{content})")
    void insert(News news);

    @Update("UPDATE news SET title = #{title}, content = #{content} WHERE id = #{id}")
    void update(News news);

    @Delete("DELETE FROM news WHERE id = #{id}")
    void deleteById(@Param("id") Integer id);
}

7、service层

service/NewsService.java

package org.example.service;


import org.example.mapper.NewsMapper;
import org.example.pojo.News;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class NewsService {
    @Autowired
    private NewsMapper newsMapper;

    public List<News> getAllNews() {
        return newsMapper.findAll();
    }

    public News getNewsById(Integer id) {
        return newsMapper.findById(id);
    }

    public void saveNews(News news) {
        newsMapper.insert(news);
    }

    public void updateNews(News news) {
        newsMapper.update(news);
    }

    public void deleteNews(Integer id) {
        newsMapper.deleteById(id);
    }
}

service/UserService.java

package org.example.service;

import org.example.pojo.User;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {
    private static final Map<String, User> users = new HashMap<>();

    static {
        // 初始化一个固定的用户
        User admin = new User();
        admin.setId(1L);
        admin.setUsername("admin");
        admin.setPassword("admin");
        users.put(admin.getUsername(), admin);
    }

    public User getUserByUsername(String username) {
        return users.get(username); // 根据用户名获取用户信息
    }
}

8、pojo层

pojo/news.java

package org.example.pojo;

import java.time.LocalDateTime;

public class News {
    private Integer id;
    private String title;
    private String content;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    // Getters and Setters
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
}

pojo/User.java

package org.example.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Data
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // Getters and Setters
    private Long id;
    private String username;
    private String password;
}

9、util层

util/SecurityUtil.java
package org.example.util;

import javax.servlet.http.HttpSession;

import org.example.pojo.User;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class SecurityUtil {
    private static final String LOGIN_USER = "loginUser";

    public static void setLoginUser(User user) {
        HttpSession session = getSession();
        session.setAttribute(LOGIN_USER, user); // 将用户信息存入会话
    }

    public static User getLoginUser() {
        HttpSession session = getSession();
        return (User) session.getAttribute(LOGIN_USER); // 从会话中获取用户信息
    }

    public static boolean isLogin() {
        return getLoginUser() != null; // 检查用户是否登录
    }

    public static void removeLoginUser() {
        HttpSession session = getSession();
        session.removeAttribute(LOGIN_USER); // 清除会话中的用户信息
    }

    private static HttpSession getSession() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
    }
}

10、主入口

MyApplication.java
package org.example;

import org.example.interceptor.LoginInterceptor;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class MyApplication implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加登录拦截器,拦截 /news/** 路径,但排除登录和登出路径
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/news/**") // 拦截新闻模块的所有请求
                .excludePathPatterns("/user/login", "/user/logout"); // 排除登录和登出页面
    }
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

11、配置文件

application.yml

spring:
  profiles:
    active: dev

application-dev.yml

server:
  port: 8081


---

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot-demo
    username: root
    password: abc123456

  # 模版配置
  thymeleaf:
    mode: HTML5
    cache: false
    encoding: UTF-8
    prefix: classpath:/templates/
    suffix: .html

# mybatis 相关配置
mybatis:
  #目的是为了省略resultType里的代码量
  type-aliases-package: org.example.pojo
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

# PageHelper 相关配置
pagehelper:
  helperDialect: mysql
  reasonable: true

12、前端模版文件

user/login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
<h1>Login</h1>
<form th:action="@{/user/login}" method="post">
    <div><label>Username: <input type="text" name="username"></label></div>
    <div><label>Password: <input type="password" name="password"></label></div>
    <div><input type="submit" value="Login"></div>
</form>
<div th:if="${error}" style="color: red;">
    <p th:text="${error}"></p>
</div>
</body>
</html>

news/list.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>News List</title>
</head>
<body>
<h1>News List</h1>
<a href="/news/add">Add News</a>
<a href="/user/logout">Logout</a>
<table border="1">
    <thead>
    <tr>
        <th>ID</th>
        <th>Title</th>
        <th>Content</th>
        <th>Actions</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="news : ${newsList}">
        <td th:text="${news.id}"></td>
        <td th:text="${news.title}"></td>
        <td th:text="${news.content}"></td>
        <td>
            <a th:href="@{'/news/edit/' + ${news.id}}">Edit</a>
            <a th:href="@{'/news/delete/' + ${news.id}}">Delete</a>
        </td>
    </tr>
    </tbody>
</table>
</body>
</html>

news/add.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Add News</title>
</head>
<body>
<h1>Add News</h1>
<form th:action="@{/news/save}" method="post" th:object="${news}">
    <label>Title:</label>
    <input type="text" th:field="*{title}" />
    <br />
    <label>Content:</label>
    <textarea th:field="*{content}"></textarea>
    <br />
    <button type="submit">Save</button>
</form>
</body>
</html>

news/edit.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Edit News</title>
</head>
<body>
<h1>Edit News</h1>
<form th:action="@{/news/update}" method="post" th:object="${news}">
  <input type="hidden" th:field="*{id}" />
  <label>Title:</label>
  <input type="text" th:field="*{title}" />
  <br />
  <label>Content:</label>
  <textarea th:field="*{content}"></textarea>
  <br />
  <button type="submit">Update</button>
</form>
</body>
</html>

四、测试运行

1、登录前界面

2、登录后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

forest_long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值