【学习日记】(SpringBoot-part 2)实体设计+用户登陆+分页显示

新闻管理系统实体设计、用户登录功能和分页显示

实体设计

1 实体关系

本系统一共需要涉及五个实体类,实体之间的映射关系如图所示
在这里插入图片描述

2 实体信息

News实体信息
在这里插入图片描述
User实体信息
在这里插入图片描述
Comment实体信息
在这里插入图片描述
分类Type和标签Tag较为简单,不画其实体图

用户登陆功能

  1. 注入依赖
    更新pom文件,注入jpa等依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tengshan</groupId>
    <artifactId>springpro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springpro</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.atlassian.commonmark</groupId>
            <artifactId>commonmark</artifactId>
            <version>0.10.0</version>
        </dependency>

        <dependency>
            <groupId>com.atlassian.commonmark</groupId>
            <artifactId>commonmark-ext-heading-anchor</artifactId>
            <version>0.10.0</version>
        </dependency>
        <dependency>
            <groupId>com.atlassian.commonmark</groupId>
            <artifactId>commonmark-ext-gfm-tables</artifactId>
            <version>0.10.0</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <!--<scope>runtime</scope>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. 新建实体类
    在po实体文件夹下新建User实体类,并且声明User的基本属性和方法
    @Entity 声明该类是个实体类
    @Table 对应数据库中表的名字(检测数据库中没有会自动新建)
@Entity
@Table(name = "t_user")
public class User {

    @Id //主键标识
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增
    private Long id;
    private String nickname;
    private String username;
    private String password;
    private String email;
    private String avatar;
    private Integer type;

    @Temporal(TemporalType.TIMESTAMP) //指定时间戳
    private Date createTime;
    @Temporal(TemporalType.TIMESTAMP) //指定时间戳
    private Date updateTime;

    //一对多关系的新闻
    @OneToMany(mappedBy = "user")
    private List<News> newsList = new ArrayList<>();

    public Long getId() {
        return id;
    }

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

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public List<News> getNewsList() {
        return newsList;
    }

    public void setNewsList(List<News> newsList) {
        this.newsList = newsList;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", nickname='" + nickname + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", avatar='" + avatar + '\'' +
                ", type=" + type +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", newsList=" + newsList +
                '}';
    }
}
  1. 新建dao接口
    基于上一次程序进度,已经新建了大概文件目录如图所示:
    在这里插入图片描述
    在dao目录下新建UserRepository接口,继承JpaRepository
    这里JpaRepository后两个参数分别表示对应的实体类和实体类中主键的类型
public interface UserRepository extends JpaRepository<User,Long> {
	//通过用户名和密码进行查询
	//这里在jpa中已经将findByUsernameAndPassword封装好了,不需要我们重新写sql语句
    User findByUsernameAndPassword(String username,String password);

}

使用jpa对数据库操作的大致流程如下
在这里插入图片描述
JPA对数据库操作时更侧重于实体类和表的映射关系 ,避免了之前需要手写sql语句的问题

  1. 新建Service接口和impl类

    在Service目录下新建一个UserService接口

public interface UserService {
    User checkUsers(String username,String password);
}

在Impl下新建一个UserServiceImpl 实现service接口中的方法

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User checkUsers(String username, String password) {
        return userRepository.findByUsernameAndPassword(username,password);
    }
}
  1. 导入前端代码
    这里用到的前端代码static文件夹和templates文件夹均由老师提供
    上传到了github 点击查看
    在这里插入图片描述

  2. 新建controller
    在web目录下新建一个admin文件夹,里面的controller均为管理员能用到的,再在admin下新建一个LoginController
    和之前的ssm项目类似,在controller中调用service接口中的方法间接调用dao层接口方法对数据库进行操作,同时controller接收来自前端的路由访问,这里同时定义了登陆和注销两个功能

@Controller
@RequestMapping("/admin")
public class LoginController {

    @Autowired
    UserService userService;

    //跳转到登陆界面

    @GetMapping
    public String loginPage(){
        return "admin/login";
    }

    @PostMapping("/login")
    public String login(@RequestParam String username , @RequestParam String password,
                        HttpSession session, RedirectAttributes attributes) {

        User user = userService.checkUsers(username, password);

        if (user != null) {
            user.setPassword(null);
            session.setAttribute("user", user);
            return "admin/index";
        } else {
            attributes.addFlashAttribute("message", "用户名或密码错误");
            return "redirect:/admin";
        }
    }

    @GetMapping("/logout")
    public String logout(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/admin";
    }
}

类别分页展示

分页展示的功能开发流程和登陆一样

  1. 新建实体类
    在po目录下新建一个Type实体类
    注解功能和登陆差不多
@Entity
@Table(name = "t_type")
public class Type {

    @Id
    @GeneratedValue(strategy =  GenerationType.IDENTITY)  //自增
    private Long id;
    private String name;

    @OneToMany(mappedBy = "type")
    private List<News> news = new ArrayList<>();

    public Type() {
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<News> getNews() {
        return news;
    }

    public void setNews(List<News> news) {
        this.news = news;
    }

    @Override
    public String toString() {
        return "Type{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
  1. 新建dao层接口
    dao目录下新建一个TypeRepository接口,在这里只需要声明继承自Jpa的实体类型为Type,不需要特别声明一个分页的接口方法,因为在Jpa中已经将这部分功能封装在里面了
public interface TypeRepository extends JpaRepository<Type,Long> {
}
  1. 新建service层接口和实现接口方法
    先在service目录下新建一个TypeService接口,声明一个列举page方法
public interface TypeService {
    Page<Type> listType(Pageable pageable);
}

再在Impl中新建一个TypeServiceImpl实现该接口方法
这里的Pageable已经封装在jpa中是一个成熟的分页工具了,在jpa中还封装了一个findAll方法

@Service
public class TypeServiceImpl implements TypeService {

    @Autowired
    private TypeRepository typeRepository;

    @Override
    public Page<Type> listType(Pageable pageable) {
        return typeRepository.findAll(pageable); //findAll方法来自jpa
    }
}
  1. 新建类别控制器

新建一个TypeController

@Controller
@RequestMapping("/admin")
public class TypeController {

    @Autowired
    private TypeService typeService;

    @RequestMapping("/types")
    public String type(@PageableDefault(size = 3,sort = {"id"},direction = Sort.Direction.DESC)
                                   Pageable pageable, Model model){
        model.addAttribute("page",typeService.listType(pageable));
        return "admin/types";
    }
}

这里的@PageableDefault 后的三个参数分别表示
size :每一页显示的数据量
sort :按什么字段排序
direction :排序方向

效果展示

登陆界面
在这里插入图片描述

由于我们本次没有写注册界面,所以登陆需要现在数据库中手动插入一条账号密码信息
在这里插入图片描述点击分类查看
在这里插入图片描述
第二页
在这里插入图片描述

这里也没有实现新建分类的功能,所以现实的数据也暂时是手动输入到数据库的,本次开发中静态资源均是来由中软国际老师提供


版权声明:本文为qq_42756396原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>