SpringBoot项目练习—个人记账笔记

SpringBoot项目—个人记账笔记

这部分的学习内容主要在于维护我的个人笔记,将springboot步骤以博客的形式作为笔记。谢谢大家的阅读。

1、项目的简单介绍

首先是任务目标:

  • 业务目标:使用 Spring Boot + Mybatis + tk Mybatis + Thymeleaf 完成个 人记账管理
  • 技能目标: Spring Boot、tk Mybatis、Thymeleaf、MySQL

其中的任务过程如下:

1.账单分类查询 
2.账单分页查询 
3.账单添加 
4.账单修改 
5.账单删除

部分截图实现如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

大致是三个页面,其中第三个页面是修改,跟添加账单的显示类似。

以上的项目加上数据库目前已经打包成gitee打包:小艾扶/记账管理系统 - 码云

其中注意,我的MySQL使用的是8以上的版本,使用5的伙伴们就需要注意编码格式。

2、数据库表示

在这里插入图片描述

首先是账单的内容,它里面还有包含账单分类。

这里稍微介绍一下数据库即可。

3、项目的环境构建&编写

首先就是创建一个Maven项目,项目导入如下:

    <dependencies>
        <!-- 通用Mapper启动器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
        </dependency>

        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.11</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

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

添加依赖,其中包括分页、tkmybatis和springboot加上thymeleaf的前端编辑。

启动类加载:

@SpringBootApplication
@MapperScan("com.xaf.dao")
public class BillManagerApplication {
    public static void main(String[] args) {
        SpringApplication.run(BillManagerApplication.class, args);
    }
}

将src/main/resource拷贝到resource下继续使用,稍微在配置文件稍作修改:

server:
  port: 8001
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/bill-manager
  thymeleaf:
    cache: false #关闭thymeleaf缓存
  #整合mybatis
mybatis:
  type-aliases-package: com.xaf.entity #别名搜索
  mapper-locations: classpath:/mybatis/*.xml

里面根据自己的需要进行修改。

实体类:

@Table(name = "bill_")
public class Bill implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_")
    private Long id;
    @Column(name = "title_")
    private String title;
    @Column(name = "bill_time_")
    private Date billTime;
    @Column(name = "type_id_")
    private Long typeId;
    @Column(name = "price_")
    private Double price;
    @Column(name = "explain_")
    private String explain;
    /**
     * 类别名称
     */
    @Transient
    private String typeName;
    /**
     * 开始时间:用于查询
     */
    @Transient
    private Date date1;
    /**
     * 结束时间:用于查询
     */
    @Transient
    private Date date2;
    
    /**
    *加入getter和setter方法
    */
@Table(name = "bill_type_")
public class BillType implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_")
    public Long id;
    @Column(name = "name_")
    public String name;
}

简单介绍一下:

@Table(name = "bill_"):将数据库表指向里面内容
@GeneratedValue(strategy = GenerationType.IDENTITY):设置表排列
@Column(name = "id_"):对应数据库表对应名称
@Transient:设置其中的属性不随着其他属性一样被直接显示或者调用

Dao层:

public interface BillMapper extends Mapper<Bill> {
    public List<Bill> select(Bill b);
}
public interface TypeMapper extends Mapper<BillType> {
}

Service:

@Service
public class BillService {
    @Autowired
    private BillMapper billMapper;

    public List<Bill> list(Bill b) {
        return billMapper.select(b);
    }
    public int add(Bill b) {
        return billMapper.insert(b);
    }
    public Bill get(Long id) {
        return billMapper.selectByPrimaryKey(id);
    }
    public int update(Bill b) {
        return billMapper.updateByPrimaryKey(b);
    }
    public int delete(Long id) {
        return billMapper.deleteByPrimaryKey(id);
    }
    public PageInfo<Bill> listPage(Bill b, int pageNum, int pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> {
            billMapper.select(b);
        });
    }

}
@Service
public class TypeService {
    @Resource
    private TypeMapper typeMapper;
    public List<BillType> list() {
        return typeMapper.selectAll();
    }
}

跟前面学习spring一样。

Controller:

@Controller
@RequestMapping("/bill")
public class BillController {
    @Resource
    private TypeService typeService;
    @Resource
    private BillService billService;
    /**
     * 查询
     * @param b
     * @param model
     * @return
     */
    @RequestMapping("/list")
    public String list(Bill b, Model model) {
        List<BillType> types = typeService.list();
        model.addAttribute("types", types);
        List<Bill> list = billService.list(b);
        model.addAttribute("list", list);
        model.addAttribute("bill", b);
        return "/bill/list";
    }
    /**
     * 调到添加页面
     * @return
     */
    @GetMapping("/toAdd")
    public String toAdd(Model model) {
        List<BillType> types = typeService.list();
        model.addAttribute("types", types);
        return "/bill/add";
    }
    /**
     * 添加
     * @param b
     * @return
     */
    @GetMapping("/add")
    public String add(Bill b) {
        billService.add(b);
        return "redirect:/bill/list";
    }
    /**
     * 删除
     * @param id
     * @return
     */
    @GetMapping("/delete/{id}")
    public String delete(@PathVariable("id") Long id) {
        billService.delete(id);
        return "redirect:/bill/list";
    }
    /**
     * 修改
     * @param id
     * @return
     */
    @GetMapping("/toUpdate/{id}")
    public String toUpdate(@PathVariable("id") Long id, Model model) {
        List<BillType> types = typeService.list();
        model.addAttribute("types", types);
        Bill bill = billService.get(id);
        model.addAttribute("bill", bill);
        return "/bill/update";
    }
    /**
     * 修改
     * @param b
     * @return
     */
    @GetMapping("/update")
    public String update(Bill b) {
        billService.update(b);
        return "redirect:/bill/list";
    }

    /**
     * 查询
     * @param b
     * @param model
     * @return
     */
    @GetMapping("/list-page")
    public String listPage(@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize, Bill b, Model model) {
        List<BillType> types = typeService.list();
        model.addAttribute("types", types);
        PageInfo<Bill> pageInfo = billService.listPage(b, pageNum, pageSize);
        model.addAttribute("page", pageInfo);
        model.addAttribute("bill", b);
        return "/bill/list-page";
    }
}

最后就是resource下的mybatis-xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xaf.dao.BillMapper">
    <sql id="selectSql">
        SELECT
            b.id_ as id,
            b.title_ as title,
            b.bill_time_ as billTime,
            b.type_id_ as typeId,
            b.price_ as price,
            b.explain_ as `explain`,
            t.name_ as typeName
        FROM
            bill_ as b
        left join
            bill_type_ as t
        on
            b.type_id_ = t.id_
    </sql>
    <select id="select" resultType="bill">
        <include refid="selectSql"/>
        <where>
            <if test="typeId !=null">
                b.type_id_ = #{typeId}
            </if>
            <if test="title !=null">
                and b.title_ like '%${title}%'
            </if>
            <if test="date1 !=null">
                and b.bill_time_ &gt;= #{date1}
            </if>
            <if test="date2 !=null">
                and b.bill_time_ &lt;= #{date2}
            </if>
        </where>
    </select>
</mapper>

其中如下代码要看一下是否对应自己的项目路径下。

<mapper namespace="com.xaf.dao.BillMapper">

剩下的就是静态资源了,里面的静态资源需要通过后端Controller中的model.addAttribute("bill", bill);进行传值。目前我的项目时已经完成了这部分的内容。

4、附加 时间转换

@Component
public class DateConverterConfig implements Converter<String, Date> {
    private static final List<String> formarts = new ArrayList<>(4);
    static{
        formarts.add("yyyy-MM");
        formarts.add("yyyy-MM-dd");
        formarts.add("yyyy-MM-dd hh:mm");
        formarts.add("yyyy-MM-dd hh:mm:ss");
    }
    @Override
    public Date convert(String source) {
        String value = source.trim();
        if ("".equals(value)) {
            return null;
        }
        if(source.matches("^\\d{4}-\\d{1,2}$")){
            return parseDate(source, formarts.get(0));
        }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")){
            return parseDate(source, formarts.get(1));
        }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")){
            return parseDate(source, formarts.get(2));
        }else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")){
            return parseDate(source, formarts.get(3));
        }else {
            throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
        }
    }
    /**
     * 格式化日期
     * @param dateStr String 字符型日期
     * @param format String 格式
     * @return Date 日期
     */
    public Date parseDate(String dateStr, String format) {
        Date date=null;
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            date = dateFormat.parse(dateStr);
        } catch (Exception e) {
        }
        return date;
    }
}

就简单介绍一下,后面的Date parseDate方法是将String类型字符转换成Date类型字符;前面添加一个list放置格式内容,后面就对格式内容进行比较并返回。

5、前端回显(粗略)

这里稍微介绍一部分内容即可。

<div class="with:80%">
    <table class="table table-striped table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>标题</th>
            <th>时间</th>
            <th>金额</th>
            <th>类别</th>
            <th>说明</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody >
		<!-- TODO 回显查询结果-->
        <tr th:each="b,status: ${list}" th:style="${status.odd} ? 'background-color:#A3C6C8'">
            <td th:text="${b.id}">id</td>
            <td th:text="${b.title}">name</td>
            <td th:text="${b.billTime} ? ${#dates.format(b.billTime, 'yyyy-MM-dd')}">time</td>
            <td th:text="${b.price}">price</td>
            <td th:text="${b.typeName}">typeName</td>
            <td th:text="${b.explain}">explain</td>
            <td>
                <a th:href="|/bill/delete/${b.id}|">删除</a>
                <a th:href="|/bill/toUpdate/${b.id}|">修改</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

这里面显示内容时,我们使用的是thymeleaf,用th:each在行标签设置循环,将内容以行的形式呈现出来才能完成最上面展示的样式。然后设置b以list类型,将list中的各个属性输出到内容上。

List<Bill> list = billService.list(b);
model.addAttribute("list", list);

这样子就完成了基本的显示内容。

再举例一个地方:

<select name="typeId" id="typeId" class="form-control" >
	<option value="">全部</option>
	<option th:each="t: ${types}" th:value="${t.id}" th:text="${t.name}" th:selected="(${bill.typeId} == ${t.id})" ></option>
</select>

这里面就是进行下拉框的显示,也是在选择标签下设置循环,将value值传进去再显示文本。(前面的展示不需要value在于只需要能够显示即可,而这里设置value是因为还要将相关的值作为记录并回响数据。)

总结

完成了以上的步骤,就基本上离完成项目项目的基本构建不远了。这部分笔记稍微作为个人笔记使用,也希望能够被大佬批评指正。谢谢阅读。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Xiao艾扶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值