【Java】简易项目初体验

简易项目初体验

qintian发布于 1 月 23 日

需求分析

任何一个电商系统中都有一个商品子系统,而与商品相关联的都会有一个品牌信息管理子系统,在当前也为设计中我们就是要对商品品牌信息进行管理。

业务架构

在品牌(brand)管理中就是要实现对商品品牌信息的添加、修改、查询、删除等业务,如图所示:
【Java】简易项目初体验

原型设计

基于业务描述,对品牌模块的业务原型进行分析和设计,如图所示:

  • 品牌列表页面

【Java】简易项目初体验

  • 品牌编辑页面

【Java】简易项目初体验

技术架构

在品牌管理模块实现过程中,我们采用典型的c/s(client/service)架构进行实现。客户端我们基于浏览器(web)进行实现,服务端采用Tomcat,数据库使用mysql,具体应用层基于MVC分层架构进行实现。

技术栈选型

客户端技术:html、css、JavaScript、bootstrap(框架)
服务端技术:spring、mybatis、springboot、thymeleaf
数据库技术:MySQL(数据库)、SQL(编程语言)
开发工具集:jdk1.8,maven3.6.3,idea2020.2

项目环境初始化

1)JDK 1.8
2)Maven 3.6.3
3)Idea 2020.2
4)MySQL 5.7以上版本

初始化数据库

假如数据库已存在,则先删除数据库,代码如下:

drop database if exists dbbrand;

创建新的数据库,代码如下:

create database dbbrand default character set utf8;

设计并创建品牌(Brand)表

打开数据库,语句如下:

use dbbrand;

在dbbrand数据库中创建品牌表.

create table tb_brand(

id bigint primary key auto_increment,

name varchar(100) not null,

remark text,

createdTime datetime not null

)engine=InnoDB;

基于SQL脚本执行数据库初始化

drop database if exists dbbrand;

create database dbbrand default character set utf8;

use dbbrand;

create table tb_brand(

id bigint primary key auto_increment,

name varchar(100) not null,

remark text,

createdTime datetime not null

)engine=InnoDB;

【Java】简易项目初体验
将以上数据库设计脚本写到brand.sql中,然后按如下步骤执行:

打开mysql自带客户端,登录mysql,指令如下:

mysql -uroot -proot

设置客户端编码,指令如下:

set names utf8;

执行sql脚本,指令如下:

source d:/brand.sql

脚本执行成功以后,在客户端查询数据之前,先执行如下语句:

set names gbk;

【Java】简易项目初体验

创建springboot项目Module

打开idea,然后基于设计,创建项目module,如图所示:

【Java】简易项目初体验

添加项目Module依赖

  • MySQL 驱动

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

  • Srping Jdbc 提供了HikariCP连接池

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jdbc</artifactId>

</dependency>

  • MyBatis 资源

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.1.3</version>

</dependency>

  • Spring Web 依赖 (内置一个tomcat服务)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

  • Thymeleaf 依赖 (html模板引擎)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

项目Module基础配置

打开项目Module配置文件application.properties,并添加如下内容:

#spring server

server.port=80

# spring datasource

spring.datasource.url=jdbc:mysql:///dbbrand?serverTimezone=GMT%2B8&characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=root

# spring mybatis

mybatis.mapper-locations=classpath:/mapper/*/*.xml

# spring log

logging.level.com.cy=debug

#spring thymeleaf

spring.thymeleaf.cache=false

spring.thymeleaf.prefix=classpath:/templates/

spring.thymeleaf.suffix=.html

启动项目进行初步环境测试分析

  • 端口号被占用

【Java】简易项目初体验

  • 数据库连接错误

【Java】简易项目初体验

项目品牌模块核心API分析与设计

基于分层架构设计思想,现对品牌API进行设计,如图所示:
【Java】简易项目初体验

品牌数据的查询及呈现

业务描述

将数据库中的品牌信息查询出来,然后在客户端基于HTML技术进行呈现,如图所示:
【Java】简易项目初体验

服务端时序访问设计

基于查询请求,进行访问时序设计,如图所示:
【Java】简易项目初体验

【Java】简易项目初体验

说明:
1.客户端先通过url发出一个请求到Tomcat服务器,再由Tomcat调用前端控制器dispatcherServlet;
2.前端控制器将接受到的请求分发到处理器映射器(HandlerMapping),处理器映射器再根据xml配置、注解找到最终要执行的(Handler),然后生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
3.DispatcherServlet调用HandlerAdapter处理器适配器,HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。 Controller执行完成返回ModelAndView,HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet;
4.DispatcherServlet将ModelAndView传给ViewReslover视图解析器,经过视图解析器解析,加上前缀、后缀, ViewReslover解析后返回具体View;
5.DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中),DispatcherServlet响应用户。

补充:
【Java】简易项目初体验

领域对象(POJO)对象设计及实现

所谓领域对象,就是指数据层、业务层、控制层等各个领域可能都需要用到POJO这个对象,所以称之为“领域对象”!

设置Brand对象,基于此对象封装从数据库查询到的品牌信息,代码如下:

package com.cy.pj.brand.pojo;

import java.util.Date;

public class Brand {

private Integer id;

private String name;

private String remark;

private Date createdTime;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getRemark() {

return remark;

}

public void setRemark(String remark) {

this.remark = remark;

}

public Date getCreatedTime() {

return createdTime;

}

public void setCreatedTime(Date createdTime) {

this.createdTime = createdTime;

}

@Override

public String toString() {

return "Brand{" +

"id=" + id +

", name='" + name + ''' +

", remark='" + remark + ''' +

", createdTime=" + createdTime +

'}';

}

}

数据逻辑对象(DAO)查询方法设计及实现

设计用于访问Brand数据的数据访问对象及方法,其关键步骤如下:

第一步:定义BrandDao接口,代码如下:

package com.cy.pj.brand.dao;

@Mapper

public interface BrandDao{

}

第二步:在BrandDao中定义品牌查询方法,代码如下:

List<Brand> findBrands(String name);

第三步:基于查询方法定义SQL映射.
在resources目录中创建mapper/brand目录,并在目录中添加BrandMapper.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.cy.pj.brand.dao.BrandDao">

<select id="findBrands" resultType="com.cy.pj.brand.pojo.Brand">

select id,name,remark,createdTime

from tb_brand

<if test="name!=null and name!=''">

where name like concat("%",#{name},"%")

</if>

</select>

</mapper>

其中:concat为mysql中提供的字符串连接函数.

第四步:对数据层的查询方法进行单元测试,代码如下:

package com.cy.pj.brand.dao;

@SpringBootTests

public class BrandDaoTests{

@Autowired

private BrandDao brandDao;

@Test

void testFindBrands(){

List<Brand> list=brandDao.findBrands("TCL");

for(Brand b:list){

System.out.println(b);

}

}

}

第五步:测试过程中的BUG分析?

  • BindingException,如图所示:

【Java】简易项目初体验

  • ExecutorException,如图所示:

【Java】简易项目初体验

业务逻辑对象(service)查询方法设计及实现

业务逻辑对象负责模块的具体业务处理,例如参数校验,事务控制,权限控制,日志记录等.

第一步:定义业务接口

package com.cy.pj.brand.service;

public interface BrandService{

}

第二步:在BrandService接口中添加品牌查询方法

List<Brand> findBrands(String name);

第三步:定义BrandService接口实现类BrandServiceImpl.

package com.cy.pj.brand.service.impl;

@Service

public class BrandServiceImpl implements BrandService{

private static final Logger log=

LoggerFactory.getLogger(BrandServiceImpl.class);

@Autowired

private BrandDao brandDao;

public List<Brand> findBrands(String name){

long t1=System.currentTimeMillis();

List<Brand> list=brandDao.findBrands(name);

long t2=System.currentTimeMillis();

log.info("findBrands->time->{}",(t2-t1));

return list;

}

}

第三步:定义BrandService接口方法的单元测试类,并业务进行测试分析

package com.cy.pj.brand.service;

@SpringBootTest

public class BrandServiceTests{

@Autowired

private BrandService brandService;

@Test

void testFindBrands(){

List<Brand> list=brandService.findBrands();

for(Brand b:list){

System.out.println(b);

}

}

}

第四步:测试过程中的Bug分析

  • NoSuchBeanDefinition,如图所示:

【Java】简易项目初体验

  • NullPointerException,如图所示:

【Java】简易项目初体验

控制逻辑对象(Controller)查询方法设计及实现

在控制逻辑对象中主要是负责请求和响应逻辑控制,例如请求url映射,参数映射,请求方式,结果集的封装,解析,响应的设计等.

第一步:定义Controller类

package com.cy.pj.brand.controller;

@Controller

public class BrandController{

@Autowired

private BrandService brandService;

}

第二步:在Controller添加处理查询请求的方法

@GetMapping(value={"/brand/doFindBrands/{name}","/brand/doFindBrands"})

public String doFindBrands(@PathVariable(required = false) String name, Model model){

List<Brand> list=brandService.findBrands(name);

model.addAttribute("list", list);

return "brand/brand";//第一个brand为目录,第二brand为view name

}

其中,
1)@GetMapping描述方法时,表示这个方法只能处理Get请求,注解内部的value属性可以指定多个url.
2)@PathVariable 用于描述方法参数,表示方法参数的值可以来自url中{}内部的变量值,required=false表示参数可以不传值.

客户端品牌列表页面设计及实现

在项目的templates目录下创建brand目录并添加brand.html页面,其关键代码如下:

<table>

<thead>

<tr>

<th>id</th>

<th>name</th>

<th>createdTime</th>

</tr>

</thead>

<tbody>

<tr th:each="brand: ${list}">

<td th:text="${brand.id}">10</td>

<td th:text="${brand.name}">AAA</td>

<td th:text="${#dates.format(brand.createdTime, 'yyyy/MM/dd

HH:mm')}">2020/10/11</td>

</tr>

</tbody>

</table>

其中:
1)${}为thymeleaf为中的EL表达式,用于从服务端model中获取数据
2)th:each为thymeleaf定义的自定义标签属性,用于迭代数据.
3)th:text为thymeleaf定义的自定义标签属性,用于设置文本内容

启动服务进行访问测试并对结果进行分析

启动服务,打开浏览器输入指定url,进行访问,其数据呈现过程,如图所示:
【Java】简易项目初体验

启动及运行过程中的Bug分析及解决方案

  • 页面元素解析异常,如图所示:

【Java】简易项目初体验

  • 模板页面找不到,如图所示:

【Java】简易项目初体验

品牌模块删除业务分析及实现

业务描述

在品牌列表页面中,点击当前行记录后面的删除按钮,基于当前行的记录id执行品牌删除操作,删除成功以后,重新刷新页面.如图所示:

【Java】简易项目初体验

业务时序分析与设计

客户端向服务端发起删除请求,服务器端的处理时序如下:

【Java】简易项目初体验

数据逻辑对象(DAO)中删除方法设计及实现

基于业务,在BrandDao接口中添加删除方法,代码如下:

int deleteById(Integer id);

基于删除方法,定义SQL映射(本次直接以注解方式进行定义),代码如下:

@Delete("delete from tb_brand where id=#{id}")

int deleteById(Integer id);

在BrandDaoTests单元测试类中添加单元测试方法,对删除操作进行测试,关键代码如下

@Test

void testDeleteById(){

int rows=brandDao.deleteById(10);

System.out.println("rows="+rows);

}

业务逻辑对象(Service)中删除方法设计及实现

在业务逻辑对象方法中,要处理删除操作需要的一些业务逻辑(后续有参数校验,权限控制,....).

第一步:在BrandService接口中添加,品牌删除的业务方法,代码如下:

int deleteById(Integer id);

第二步:在BrandServiceImpl类中添加删除业务的具体实现,代码如下:

public int deleteById(Integer id){

//1.参数校验

//2.执行删除业务

int rows=brandDao.deleteById(id);

//3.校验结果并返回

return rows;

}

第三步:在BrandServiceTests类中添加单元测试方法,对其删除业务做测试?

@Test

void testDeleteById(){

int rows=brandService.deleteById(10);

System.out.println("row="+row);

}

第四步:测试过程中的Bug分析?

控制逻辑对象(Controller)中删除方法设计及实现

在控制层对象中定义处理删除请求的方法,具体代码如下:

@GetMapping("/brand/doDeleteById/{id}")

public String doDeleteById(@PathVariable Integer id,Model model){

brandService.deleteById(id);

List<Brand> list=brandService.findBrands();

model.addAttribute("list",list);

return "brand/brand";

}

客户端删除按钮事件定义及处理

在tbody的tr中添加一列,代码如下:

<td>

<button type="button" th:onclick="doDeleteById([[${brand.id}]])">delete</button>

</td>

定义javascript函数,处理删除事件,代码如下:

function doDeleteById(id){

//给出提示信息

if(!confirm("您确认删除吗"))return;//confirm为浏览器中window对象的函数

//执行删除业务

location.href=`http://localhost/brand/doDeleteById/${id}`;

}

品牌模块添加业务分析及实现

业务描述

在列表页面上,设计添加按钮,当点击添加按钮时,跳转到添加页面,然后在添加页面上数据品牌信息,点击Save按钮就数据提交到服务端进行保存.

【Java】简易项目初体验

【Java】简易项目初体验

添加时序分析及设计

【Java】简易项目初体验

数据逻辑对象(Dao)中方法设计及实现

第一步:在BrandDao中添加用于保存品牌信息的方法,代码如下:

int insertBrand(Brand brand);

第二步:在BrandMapper中添加品牌保存操作对应的sql映射,代码如下:

<insert id="insertBrand">

insert into tb_brand

(name,remark,createdTime)

values

(#{name},#{remark},now())

</insert>

业务逻辑对象(Service)中方法设计及实现

第一步:在BrandService业务接口中中定义用于保存品牌信息的方法,代码如下:

int saveBrand(Brand brand);

第二步:在BrandServiceImpl业务实现类中添加保存品牌信息的具体实现,代码如下:

public int saveBrand(Brand brand){

int rows=brandDao.insertBrand(brand);

return rows;

}

控制逻辑对象(Controller)中方法设计及实现

第一步:在BrandController中添加用于处理请求添加页面的方法,代码如下:

@GetMapping("https://segmentfault.com/brand/doAddUI")

public String doAddUI(){

return "brand/brand-add";

}

第二步:在BrandController添加用于处理添加品牌信息页面的方法,代码如下:

@PostMapping("/brand/doSaveBrand")

public String doSaveBrand(Brand brand,Model model){

System.out.println("save.brand="+brand);

brandService.saveBrand(brand);

List<Brand> list=brandService.findBrands(null);

model.addAttribute("list",list);

return "brand/brand";

}

品牌添加操作客户端业务分析、设计及实现.

第一步:设计品牌添加页面brand-add.html,代码如下

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="UTF-8">

<title>Title</title>

<link rel="stylesheet" href="https://segmentfault.com/bootstrap/css/bootstrap.css">

</head>

<body>

<div class="container">

<h1>The Brand Add Page</h1>

<form th:action="@{/brand/doSaveBrand}" method="post">

<div class="form-group">

<label for="nameId">Name</label>

<input type="text" class="form-control" name="name" id="nameId" placeholder="Brand Name">

</div>

<div class="form-group">

<label for="remarkId">Remark</label>

<textarea class="form-control" rows="5" cols="100" name="remark" id="remarkId">

</textarea>

</div>

<button type="submit" class="btn btn-default">Submit</button>

</form>

</div>

</body>

</html>

第二步:在品牌列表brand.html页面,设计添加按钮,代码如下:

<button type="button" onclick="doAddUI()" class="btn btn-primary btn-sm">Add Brand</button>

第三步:点击添加按钮时,加载品牌添加页面,事件处理函数如下:

function doAddUI(){

location.href="https://segmentfault.com/brand/doAddUI";

}

启动服务进行访问测试分析

【Java】简易项目初体验

【Java】简易项目初体验

启动及运行过程中的BUG分析

  • 客户端提交到服务端的数据拿不到?

【Java】简易项目初体验

品牌模块修改业务分析及实现

业务描述

在品牌列表页面,点击当前行的修改按钮,先基于id查询当前行记录,并将记录呈现在编辑页面,如图所示:

【Java】简易项目初体验

【Java】简易项目初体验

业务时序分析与设计

基于id查询品牌信息并呈现在页面上,其时序分析如图所示:

【Java】简易项目初体验

在品牌编辑页面,编辑数据,点击save按钮保存更新,其时序如图所示:
【Java】简易项目初体验

数据逻辑对象(Dao)中方法设计与实现

在BrandDao中添加基于id查询品牌信息的方法及SQL映射,代码如下:

@Select("select * from tb_brand where id=#{id}")

Brand findById(Integer id);

在BrandDao中添加基于id执行品牌更新的方法及SQL映射,代码如下:

 @Update("update tb_brand set name=#{name},remark=#{remark} where id=#{id}")

int updateBrand(Brand Brand);

业务逻辑对象(Service)中方法设计与实现

在BrandService 中添加基于id查询品牌信息和更新品牌信息的方法,代码如下:

Brand findById(Integer id);

int updateBrand(Brand brand);

在BrandServiceImpl中基于id查询品牌信息和更新品牌信息的方法,代码如下:

 @Override

public Brand findById(Integer id) {

//.....

return brandDao.findById(id);

}

 @Override

public int updateBrand(Brand brand) {

return brandDao.updateBrand(brand);

}

控制逻辑对象(Controller)中方法设计与实现

在BrandController中添加基于id查询品牌信息的方法,代码如下:

 @RequestMapping("/brand/doFindById/{id}")

public String doFindById(@PathVariable Integer id,Model model) {

Brand brand=brandService.findById(id);

model.addAttribute("brand",brand);

return "/brand/brand-update";

}

在BrandController中添加更新品牌信息的方法,代码如下:

 @RequestMapping("/brand/doUpdateBrand")

public String doUpdateBrand(Brand brand,Model model) {

brandService.updateBrand(brand);

List<Brand> list=brandService.findBrands(null);

model.addAttribute("list",list);

return "brand/brand";

}

客户端品牌编辑页面设计与实现

第一步:设计品牌修改页面brand-update.html,代码如下

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="UTF-8">

<title>Title</title>

<link rel="stylesheet" href="https://segmentfault.com/bootstrap/css/bootstrap.css">

</head>

<body>

<div class="container">

<h1>The Brand Update Page</h1>

<form th:action="@{/brand/doUpdateBrand}" method="post">

<input type="hidden" name="id" th:value="${brand.id}">

<div class="form-group">

<label for="nameId">Name</label>

<input type="text" class="form-control" name="name" id="nameId" th:value="${brand.name}" placeholder="Brand Name">

</div>

<div class="form-group">

<label for="remarkId">Remark</label>

<textarea class="form-control" rows="5" cols="100" name="remark" th:text="${brand.remark}" id="remarkId">

</textarea>

</div>

<button type="submit" class="btn btn-default">Submit</button>

</form>

</div>

</body>

</html>

启动Tomcat服务进行访问测试分析

启动服务,先进入品牌列表页面,然后点击修改按钮如图所示:
【Java】简易项目初体验
此时,进入品牌编辑页面,如图所示:
【Java】简易项目初体验
在品牌编辑页面,编辑数据以后,点击save按钮,执行更新操作。

启动及运行过程中的BUG分析

  • 405 异常

【Java】简易项目初体验

  • 呈现的数据不正确

【Java】简易项目初体验

  • 页面元素解析异常

【Java】简易项目初体验

总结(Summary)

本章节,主要基于学过的springboot,Hikaricp,MyBatis,Spring,Thymeleaf等技术,对商品品牌模块做了具体实现。重点掌握其基本设计及实现过程。

mysqljavaspringspringbootthymeleaf

本文系转载,阅读原文

https://segmentfault.com/a/1190000037732462

阅读 44更新于 1 月 23 日

avatar

qintian

1 声望

0 粉丝

0 条评论

得票时间

avatar

qintian

1 声望

0 粉丝

宣传栏

需求分析

任何一个电商系统中都有一个商品子系统,而与商品相关联的都会有一个品牌信息管理子系统,在当前也为设计中我们就是要对商品品牌信息进行管理。

业务架构

在品牌(brand)管理中就是要实现对商品品牌信息的添加、修改、查询、删除等业务,如图所示:
【Java】简易项目初体验

原型设计

基于业务描述,对品牌模块的业务原型进行分析和设计,如图所示:

  • 品牌列表页面

【Java】简易项目初体验

  • 品牌编辑页面

【Java】简易项目初体验

技术架构

在品牌管理模块实现过程中,我们采用典型的c/s(client/service)架构进行实现。客户端我们基于浏览器(web)进行实现,服务端采用Tomcat,数据库使用mysql,具体应用层基于MVC分层架构进行实现。

技术栈选型

客户端技术:html、css、JavaScript、bootstrap(框架)
服务端技术:spring、mybatis、springboot、thymeleaf
数据库技术:MySQL(数据库)、SQL(编程语言)
开发工具集:jdk1.8,maven3.6.3,idea2020.2

项目环境初始化

1)JDK 1.8
2)Maven 3.6.3
3)Idea 2020.2
4)MySQL 5.7以上版本

初始化数据库

假如数据库已存在,则先删除数据库,代码如下:

drop database if exists dbbrand;

创建新的数据库,代码如下:

create database dbbrand default character set utf8;

设计并创建品牌(Brand)表

打开数据库,语句如下:

use dbbrand;

在dbbrand数据库中创建品牌表.

create table tb_brand(

id bigint primary key auto_increment,

name varchar(100) not null,

remark text,

createdTime datetime not null

)engine=InnoDB;

基于SQL脚本执行数据库初始化

drop database if exists dbbrand;

create database dbbrand default character set utf8;

use dbbrand;

create table tb_brand(

id bigint primary key auto_increment,

name varchar(100) not null,

remark text,

createdTime datetime not null

)engine=InnoDB;

【Java】简易项目初体验
将以上数据库设计脚本写到brand.sql中,然后按如下步骤执行:

打开mysql自带客户端,登录mysql,指令如下:

mysql -uroot -proot

设置客户端编码,指令如下:

set names utf8;

执行sql脚本,指令如下:

source d:/brand.sql

脚本执行成功以后,在客户端查询数据之前,先执行如下语句:

set names gbk;

【Java】简易项目初体验

创建springboot项目Module

打开idea,然后基于设计,创建项目module,如图所示:

【Java】简易项目初体验

添加项目Module依赖

  • MySQL 驱动

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

  • Srping Jdbc 提供了HikariCP连接池

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jdbc</artifactId>

</dependency>

  • MyBatis 资源

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.1.3</version>

</dependency>

  • Spring Web 依赖 (内置一个tomcat服务)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

  • Thymeleaf 依赖 (html模板引擎)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

项目Module基础配置

打开项目Module配置文件application.properties,并添加如下内容:

#spring server

server.port=80

# spring datasource

spring.datasource.url=jdbc:mysql:///dbbrand?serverTimezone=GMT%2B8&characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=root

# spring mybatis

mybatis.mapper-locations=classpath:/mapper/*/*.xml

# spring log

logging.level.com.cy=debug

#spring thymeleaf

spring.thymeleaf.cache=false

spring.thymeleaf.prefix=classpath:/templates/

spring.thymeleaf.suffix=.html

启动项目进行初步环境测试分析

  • 端口号被占用

【Java】简易项目初体验

  • 数据库连接错误

【Java】简易项目初体验

项目品牌模块核心API分析与设计

基于分层架构设计思想,现对品牌API进行设计,如图所示:
【Java】简易项目初体验

品牌数据的查询及呈现

业务描述

将数据库中的品牌信息查询出来,然后在客户端基于HTML技术进行呈现,如图所示:
【Java】简易项目初体验

服务端时序访问设计

基于查询请求,进行访问时序设计,如图所示:
【Java】简易项目初体验

【Java】简易项目初体验

说明:
1.客户端先通过url发出一个请求到Tomcat服务器,再由Tomcat调用前端控制器dispatcherServlet;
2.前端控制器将接受到的请求分发到处理器映射器(HandlerMapping),处理器映射器再根据xml配置、注解找到最终要执行的(Handler),然后生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
3.DispatcherServlet调用HandlerAdapter处理器适配器,HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。 Controller执行完成返回ModelAndView,HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet;
4.DispatcherServlet将ModelAndView传给ViewReslover视图解析器,经过视图解析器解析,加上前缀、后缀, ViewReslover解析后返回具体View;
5.DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中),DispatcherServlet响应用户。

补充:
【Java】简易项目初体验

领域对象(POJO)对象设计及实现

所谓领域对象,就是指数据层、业务层、控制层等各个领域可能都需要用到POJO这个对象,所以称之为“领域对象”!

设置Brand对象,基于此对象封装从数据库查询到的品牌信息,代码如下:

package com.cy.pj.brand.pojo;

import java.util.Date;

public class Brand {

private Integer id;

private String name;

private String remark;

private Date createdTime;

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getRemark() {

return remark;

}

public void setRemark(String remark) {

this.remark = remark;

}

public Date getCreatedTime() {

return createdTime;

}

public void setCreatedTime(Date createdTime) {

this.createdTime = createdTime;

}

@Override

public String toString() {

return "Brand{" +

"id=" + id +

", name='" + name + ''' +

", remark='" + remark + ''' +

", createdTime=" + createdTime +

'}';

}

}

数据逻辑对象(DAO)查询方法设计及实现

设计用于访问Brand数据的数据访问对象及方法,其关键步骤如下:

第一步:定义BrandDao接口,代码如下:

package com.cy.pj.brand.dao;

@Mapper

public interface BrandDao{

}

第二步:在BrandDao中定义品牌查询方法,代码如下:

List<Brand> findBrands(String name);

第三步:基于查询方法定义SQL映射.
在resources目录中创建mapper/brand目录,并在目录中添加BrandMapper.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.cy.pj.brand.dao.BrandDao">

<select id="findBrands" resultType="com.cy.pj.brand.pojo.Brand">

select id,name,remark,createdTime

from tb_brand

<if test="name!=null and name!=''">

where name like concat("%",#{name},"%")

</if>

</select>

</mapper>

其中:concat为mysql中提供的字符串连接函数.

第四步:对数据层的查询方法进行单元测试,代码如下:

package com.cy.pj.brand.dao;

@SpringBootTests

public class BrandDaoTests{

@Autowired

private BrandDao brandDao;

@Test

void testFindBrands(){

List<Brand> list=brandDao.findBrands("TCL");

for(Brand b:list){

System.out.println(b);

}

}

}

第五步:测试过程中的BUG分析?

  • BindingException,如图所示:

【Java】简易项目初体验

  • ExecutorException,如图所示:

【Java】简易项目初体验

业务逻辑对象(service)查询方法设计及实现

业务逻辑对象负责模块的具体业务处理,例如参数校验,事务控制,权限控制,日志记录等.

第一步:定义业务接口

package com.cy.pj.brand.service;

public interface BrandService{

}

第二步:在BrandService接口中添加品牌查询方法

List<Brand> findBrands(String name);

第三步:定义BrandService接口实现类BrandServiceImpl.

package com.cy.pj.brand.service.impl;

@Service

public class BrandServiceImpl implements BrandService{

private static final Logger log=

LoggerFactory.getLogger(BrandServiceImpl.class);

@Autowired

private BrandDao brandDao;

public List<Brand> findBrands(String name){

long t1=System.currentTimeMillis();

List<Brand> list=brandDao.findBrands(name);

long t2=System.currentTimeMillis();

log.info("findBrands->time->{}",(t2-t1));

return list;

}

}

第三步:定义BrandService接口方法的单元测试类,并业务进行测试分析

package com.cy.pj.brand.service;

@SpringBootTest

public class BrandServiceTests{

@Autowired

private BrandService brandService;

@Test

void testFindBrands(){

List<Brand> list=brandService.findBrands();

for(Brand b:list){

System.out.println(b);

}

}

}

第四步:测试过程中的Bug分析

  • NoSuchBeanDefinition,如图所示:

【Java】简易项目初体验

  • NullPointerException,如图所示:

【Java】简易项目初体验

控制逻辑对象(Controller)查询方法设计及实现

在控制逻辑对象中主要是负责请求和响应逻辑控制,例如请求url映射,参数映射,请求方式,结果集的封装,解析,响应的设计等.

第一步:定义Controller类

package com.cy.pj.brand.controller;

@Controller

public class BrandController{

@Autowired

private BrandService brandService;

}

第二步:在Controller添加处理查询请求的方法

@GetMapping(value={"/brand/doFindBrands/{name}","/brand/doFindBrands"})

public String doFindBrands(@PathVariable(required = false) String name, Model model){

List<Brand> list=brandService.findBrands(name);

model.addAttribute("list", list);

return "brand/brand";//第一个brand为目录,第二brand为view name

}

其中,
1)@GetMapping描述方法时,表示这个方法只能处理Get请求,注解内部的value属性可以指定多个url.
2)@PathVariable 用于描述方法参数,表示方法参数的值可以来自url中{}内部的变量值,required=false表示参数可以不传值.

客户端品牌列表页面设计及实现

在项目的templates目录下创建brand目录并添加brand.html页面,其关键代码如下:

<table>

<thead>

<tr>

<th>id</th>

<th>name</th>

<th>createdTime</th>

</tr>

</thead>

<tbody>

<tr th:each="brand: ${list}">

<td th:text="${brand.id}">10</td>

<td th:text="${brand.name}">AAA</td>

<td th:text="${#dates.format(brand.createdTime, 'yyyy/MM/dd

HH:mm')}">2020/10/11</td>

</tr>

</tbody>

</table>

其中:
1)${}为thymeleaf为中的EL表达式,用于从服务端model中获取数据
2)th:each为thymeleaf定义的自定义标签属性,用于迭代数据.
3)th:text为thymeleaf定义的自定义标签属性,用于设置文本内容

启动服务进行访问测试并对结果进行分析

启动服务,打开浏览器输入指定url,进行访问,其数据呈现过程,如图所示:
【Java】简易项目初体验

启动及运行过程中的Bug分析及解决方案

  • 页面元素解析异常,如图所示:

【Java】简易项目初体验

  • 模板页面找不到,如图所示:

【Java】简易项目初体验

品牌模块删除业务分析及实现

业务描述

在品牌列表页面中,点击当前行记录后面的删除按钮,基于当前行的记录id执行品牌删除操作,删除成功以后,重新刷新页面.如图所示:

【Java】简易项目初体验

业务时序分析与设计

客户端向服务端发起删除请求,服务器端的处理时序如下:

【Java】简易项目初体验

数据逻辑对象(DAO)中删除方法设计及实现

基于业务,在BrandDao接口中添加删除方法,代码如下:

int deleteById(Integer id);

基于删除方法,定义SQL映射(本次直接以注解方式进行定义),代码如下:

@Delete("delete from tb_brand where id=#{id}")

int deleteById(Integer id);

在BrandDaoTests单元测试类中添加单元测试方法,对删除操作进行测试,关键代码如下

@Test

void testDeleteById(){

int rows=brandDao.deleteById(10);

System.out.println("rows="+rows);

}

业务逻辑对象(Service)中删除方法设计及实现

在业务逻辑对象方法中,要处理删除操作需要的一些业务逻辑(后续有参数校验,权限控制,....).

第一步:在BrandService接口中添加,品牌删除的业务方法,代码如下:

int deleteById(Integer id);

第二步:在BrandServiceImpl类中添加删除业务的具体实现,代码如下:

public int deleteById(Integer id){

//1.参数校验

//2.执行删除业务

int rows=brandDao.deleteById(id);

//3.校验结果并返回

return rows;

}

第三步:在BrandServiceTests类中添加单元测试方法,对其删除业务做测试?

@Test

void testDeleteById(){

int rows=brandService.deleteById(10);

System.out.println("row="+row);

}

第四步:测试过程中的Bug分析?

控制逻辑对象(Controller)中删除方法设计及实现

在控制层对象中定义处理删除请求的方法,具体代码如下:

@GetMapping("/brand/doDeleteById/{id}")

public String doDeleteById(@PathVariable Integer id,Model model){

brandService.deleteById(id);

List<Brand> list=brandService.findBrands();

model.addAttribute("list",list);

return "brand/brand";

}

客户端删除按钮事件定义及处理

在tbody的tr中添加一列,代码如下:

<td>

<button type="button" th:onclick="doDeleteById([[${brand.id}]])">delete</button>

</td>

定义javascript函数,处理删除事件,代码如下:

function doDeleteById(id){

//给出提示信息

if(!confirm("您确认删除吗"))return;//confirm为浏览器中window对象的函数

//执行删除业务

location.href=`http://localhost/brand/doDeleteById/${id}`;

}

品牌模块添加业务分析及实现

业务描述

在列表页面上,设计添加按钮,当点击添加按钮时,跳转到添加页面,然后在添加页面上数据品牌信息,点击Save按钮就数据提交到服务端进行保存.

【Java】简易项目初体验

【Java】简易项目初体验

添加时序分析及设计

【Java】简易项目初体验

数据逻辑对象(Dao)中方法设计及实现

第一步:在BrandDao中添加用于保存品牌信息的方法,代码如下:

int insertBrand(Brand brand);

第二步:在BrandMapper中添加品牌保存操作对应的sql映射,代码如下:

<insert id="insertBrand">

insert into tb_brand

(name,remark,createdTime)

values

(#{name},#{remark},now())

</insert>

业务逻辑对象(Service)中方法设计及实现

第一步:在BrandService业务接口中中定义用于保存品牌信息的方法,代码如下:

int saveBrand(Brand brand);

第二步:在BrandServiceImpl业务实现类中添加保存品牌信息的具体实现,代码如下:

public int saveBrand(Brand brand){

int rows=brandDao.insertBrand(brand);

return rows;

}

控制逻辑对象(Controller)中方法设计及实现

第一步:在BrandController中添加用于处理请求添加页面的方法,代码如下:

@GetMapping("https://segmentfault.com/brand/doAddUI")

public String doAddUI(){

return "brand/brand-add";

}

第二步:在BrandController添加用于处理添加品牌信息页面的方法,代码如下:

@PostMapping("/brand/doSaveBrand")

public String doSaveBrand(Brand brand,Model model){

System.out.println("save.brand="+brand);

brandService.saveBrand(brand);

List<Brand> list=brandService.findBrands(null);

model.addAttribute("list",list);

return "brand/brand";

}

品牌添加操作客户端业务分析、设计及实现.

第一步:设计品牌添加页面brand-add.html,代码如下

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="UTF-8">

<title>Title</title>

<link rel="stylesheet" href="https://segmentfault.com/bootstrap/css/bootstrap.css">

</head>

<body>

<div class="container">

<h1>The Brand Add Page</h1>

<form th:action="@{/brand/doSaveBrand}" method="post">

<div class="form-group">

<label for="nameId">Name</label>

<input type="text" class="form-control" name="name" id="nameId" placeholder="Brand Name">

</div>

<div class="form-group">

<label for="remarkId">Remark</label>

<textarea class="form-control" rows="5" cols="100" name="remark" id="remarkId">

</textarea>

</div>

<button type="submit" class="btn btn-default">Submit</button>

</form>

</div>

</body>

</html>

第二步:在品牌列表brand.html页面,设计添加按钮,代码如下:

<button type="button" onclick="doAddUI()" class="btn btn-primary btn-sm">Add Brand</button>

第三步:点击添加按钮时,加载品牌添加页面,事件处理函数如下:

function doAddUI(){

location.href="https://segmentfault.com/brand/doAddUI";

}

启动服务进行访问测试分析

【Java】简易项目初体验

【Java】简易项目初体验

启动及运行过程中的BUG分析

  • 客户端提交到服务端的数据拿不到?

【Java】简易项目初体验

品牌模块修改业务分析及实现

业务描述

在品牌列表页面,点击当前行的修改按钮,先基于id查询当前行记录,并将记录呈现在编辑页面,如图所示:

【Java】简易项目初体验

【Java】简易项目初体验

业务时序分析与设计

基于id查询品牌信息并呈现在页面上,其时序分析如图所示:

【Java】简易项目初体验

在品牌编辑页面,编辑数据,点击save按钮保存更新,其时序如图所示:
【Java】简易项目初体验

数据逻辑对象(Dao)中方法设计与实现

在BrandDao中添加基于id查询品牌信息的方法及SQL映射,代码如下:

@Select("select * from tb_brand where id=#{id}")

Brand findById(Integer id);

在BrandDao中添加基于id执行品牌更新的方法及SQL映射,代码如下:

 @Update("update tb_brand set name=#{name},remark=#{remark} where id=#{id}")

int updateBrand(Brand Brand);

业务逻辑对象(Service)中方法设计与实现

在BrandService 中添加基于id查询品牌信息和更新品牌信息的方法,代码如下:

Brand findById(Integer id);

int updateBrand(Brand brand);

在BrandServiceImpl中基于id查询品牌信息和更新品牌信息的方法,代码如下:

 @Override

public Brand findById(Integer id) {

//.....

return brandDao.findById(id);

}

 @Override

public int updateBrand(Brand brand) {

return brandDao.updateBrand(brand);

}

控制逻辑对象(Controller)中方法设计与实现

在BrandController中添加基于id查询品牌信息的方法,代码如下:

 @RequestMapping("/brand/doFindById/{id}")

public String doFindById(@PathVariable Integer id,Model model) {

Brand brand=brandService.findById(id);

model.addAttribute("brand",brand);

return "/brand/brand-update";

}

在BrandController中添加更新品牌信息的方法,代码如下:

 @RequestMapping("/brand/doUpdateBrand")

public String doUpdateBrand(Brand brand,Model model) {

brandService.updateBrand(brand);

List<Brand> list=brandService.findBrands(null);

model.addAttribute("list",list);

return "brand/brand";

}

客户端品牌编辑页面设计与实现

第一步:设计品牌修改页面brand-update.html,代码如下

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="UTF-8">

<title>Title</title>

<link rel="stylesheet" href="https://segmentfault.com/bootstrap/css/bootstrap.css">

</head>

<body>

<div class="container">

<h1>The Brand Update Page</h1>

<form th:action="@{/brand/doUpdateBrand}" method="post">

<input type="hidden" name="id" th:value="${brand.id}">

<div class="form-group">

<label for="nameId">Name</label>

<input type="text" class="form-control" name="name" id="nameId" th:value="${brand.name}" placeholder="Brand Name">

</div>

<div class="form-group">

<label for="remarkId">Remark</label>

<textarea class="form-control" rows="5" cols="100" name="remark" th:text="${brand.remark}" id="remarkId">

</textarea>

</div>

<button type="submit" class="btn btn-default">Submit</button>

</form>

</div>

</body>

</html>

启动Tomcat服务进行访问测试分析

启动服务,先进入品牌列表页面,然后点击修改按钮如图所示:
【Java】简易项目初体验
此时,进入品牌编辑页面,如图所示:
【Java】简易项目初体验
在品牌编辑页面,编辑数据以后,点击save按钮,执行更新操作。

启动及运行过程中的BUG分析

  • 405 异常

【Java】简易项目初体验

  • 呈现的数据不正确

【Java】简易项目初体验

  • 页面元素解析异常

【Java】简易项目初体验

总结(Summary)

本章节,主要基于学过的springboot,Hikaricp,MyBatis,Spring,Thymeleaf等技术,对商品品牌模块做了具体实现。重点掌握其基本设计及实现过程。

以上是 【Java】简易项目初体验 的全部内容, 来源链接: utcz.com/a/107287.html

回到顶部