be based on Spring,MyBatis,SpringBoot,Thymeleaf Technology to achieve the addition, deletion, modification and query operation of commodity module .
preparation
1. MySQL(5.7)
2. JDK (1.8)
3. Maven (3.6.3)
4. STS(4.7.1)
Technology Architecture
Use the typical c/s Architecture for implementation , The client is implemented based on browser , Server using tomacat, Database usage mysql, The specific application layer is based on mvc Layered architecture implementation
Technology stack
client :html,css,js,bootstrap
Server side :spring,springboot,mybaties,thymeleaf
database :mysql,SQL
API Integrate
Business timing
Initialize database
Sign in mysql mysql -uroot -proot
Set the encoding format
set names utf8;
perform goods.sql file
among goods.sql The contents of the document are as follows :
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;
insert into tb_brand values (null,' lenovo ','very good',now());
insert into tb_brand values (null,' millet ','very good',now());
insert into tb_brand values (null,' beauty ','very good',now());
insert into tb_brand values (null,' Joyoung ','very good',now());
insert into tb_brand values (null,'TCL','very good',now());
insert into tb_brand values (null,' skyworth ','very good',now());
insert into tb_brand values (null,' Huawei ','very good',now());
be based on idea establish
establish module
Project profile
application.properties, Add the following :
#server
server.port=80
#server.servlet.context-path=/
#spring datasource
spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml
#spring logging
logging.level.com.cy=debug
#spring thymeleaf
spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
Add dependency
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-groovy-templates</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
The startup class checks whether it can start normally
Domain object Pojo Class definition design and implementation
First step : Definition Goods object , It is used to encapsulate the product information queried from the database .
package com.cy.pj.goods.pojo;
import java.util.Date;
public class Goods {
private Integer id;//id bigint primary key auto_increment
private String name;//name varchar(100) not null
private String remark;//remark text
private Date createdTime;//createdTime datetime
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 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 "Goods [id=" + id + ", name=" + name + ",
remark=" + remark + ", createdTime=" + createdTime + "]";
}
}
The second step :### Dao Interface method
stay GoodsDao Interface to define the commodity query method and SQL mapping , Based on this method and SQL Map to get all product information . The code is as follows :
** Dynamic code is best mapped
ordinary sql Write directly on the method with annotations **
package com.cy.pj.goods.dao;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.cy.pj.goods.pojo.Goods;
@Mapper
public interface GoodsDao {
@Select("select * from tb_brand where name like concat('%',#{name},'%')and name!=null or name!=''")
// It's too complicated , It's better to use mapping for complexity
List<Goods> findGoods(String name);
}
One of the two is mapping and annotation
Mapping code
@Mapper
public interface GoodsDao {
List<Goods> findGoods(String name);
}
stay resources Create under directory mapper file
Creating xml The mapping file
<?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.goods.Dao.GoodsDao">
<select id="findGoods" resultType="com.cy.pj.goods.pojo.Goods">
select *
from tb_brand
<if test="name!=null and name!=''">
where name like concat("%",#{name},"%")
</if>
</select>
</mapper> ```
The third step : To test
ackage com.cy.pj.goods.dao;
import com.cy.pj.goods.pojo.Goods;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class GoodsDaoTests {
@Autowired
private GoodsDao goodsDao;
@Test
void testFindGoods(){
List<Goods> goodsList=goodsDao.findGoods(null);
for(Goods g:goodsList){
System.out.println(g);
}
}
}
Test results problem analysis
- The database doesn't connect to , As shown in the figure :
- Connected to the database url Configuration problem , As shown in the figure :
- Sql Mapping the problem of repeated definition , As shown in the figure :
- Null pointer problem , As shown in the figure :
- SQL Grammar problem , As shown in the figure :
Business logic objects
The object is responsible for the specific business processing of the module, such as : journal , Permissions, etc.
First step : Define business interface , Add brand query method
import com.cy.pj.goods.pojo.Goods;
import java.util.List;
public interface GoodsService {
List<Goods> findBrannds(String name);
}
The second step : Define interface implementation classes
package com.cy.pj.goods.pojo;
import com.cy.pj.goods.Dao.GoodsDao;
import com.cy.pj.goods.Dao.GoodsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class GoodsImp implements GoodsService {
private static final Logger log= LoggerFactory.getLogger(GoodsImp.class);
@Autowired
private GoodsDao goodsDao;
@Override
public List<Goods> findBrannds(String name) {
long t1=System.currentTimeMillis();
List<Goods> list=goodsDao.findGoods(name);
long t2=System.currentTimeMillis();
log.info("find->",t2-t1);
return list;
}
}
The third step : Unit test
package com.cy.pj;
import com.cy.pj.goods.Dao.GoodsService;
import com.cy.pj.goods.pojo.Goods;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class BrandTest {
@Autowired
private GoodsService goodsService;
@Test
void dou(){
List<Goods> list=goodsService.findGoods(" millet ");
System.out.println(list.size());
Assertions.assertEquals(1, list.size());// Assertion testing
System.out.println("OK");
list.forEach(brand->System.out.println());//jdk1.8lambda expression
}
}
Controller Object method definition and implementation
Definition GoodsController class , And add doGoodsUI Method , Add query product information code , And store the inquired product information to model, And back to goods page .
package com.cy.pj.goods;
import com.cy.pj.goods.one.GoodsService;
import com.cy.pj.goods.pojo.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@Controller
public class CollerGoods {
@Autowired
private GoodsService goodsService;
//@PathVariable Used to modify parameters , tell mvc, Parameters come from url
@GetMapping(value = {"/goods/doFind","/goods/doFind/{name}"})
public String doFind(@PathVariable(required = false) String name, Model model){
List<Goods> list=goodsService.findGoods(name);
model.addAttribute("list", list);
return "brand";
}
}
test :http://localhost/goods/doFind...
Transform into :
package com.cy.pj.goods;
import com.cy.pj.goods.one.GoodsService;
import com.cy.pj.goods.pojo.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class CollerGoods {
@Autowired
private GoodsService goodsService;
@GetMapping("/goods/doFind")
public String doFind( String name, Model model){
List<Goods> list=goodsService.findGoods(name);
model.addAttribute("list", list);
return "brand";
}
}
test :http://localhost/goods/doFind
Client submits data to server , Not received on the server ?
It depends on the way the client submits data and the server requests
When the server responds to the client data , If the client does not receive ?
First detect the data before the server response data
brand.html:
<html>
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all"
href="../../css/gtvg.css" data-th-href="@{/css/gtvg.css}" />
</head>
<body>
<!-- The traditional way -->
<!--<form th:action="@{/goods/doFind}" method="get">-->
<!-- <input type="text" name="name">-->
<!-- <input type="submit" value=" Inquire about ">-->
<!-- <input type="submit" value=" Back to the home page ">-->
<!--</form>-->
<!--rs-->
<form>
<input type="text" name="name">
<input type="button" onclick="doba()" value=" Inquire about ">
<input type="button" onclick="doqu()" value=" Back to the home page ">
</form>
<table width="50%">
<thead>
<th>id</th>
<th>name</th>
<th>remark</th>
<th>createdTime</th>
<th>operation</th>
</thead>
<tbody>
<tr th:each="g:${list}">
<td th:text="${g.id}">1</td>
<td th:text="${g.name}">MySQL</td>
<td th:text="${g.remark}">DBMS</td>
<td th:text="${#dates.format(g.createdTime, 'yyyy/MM/dd HH:mm')}">2020/07/03</td>
<td><a>delete</a></td>
</tr>
</tbody>
</table>
<script>
function doba(){
// obtain form Data in form
var name=document.forms[0].name.value;
console.log("name",name);
var url="http://localhost/goods/doFind/"+name;
location.href=url;
}
function doqu(){
var url="http://localhost/goods/doFind/";
// Access to the url( I'll change asynchrony later )
location.href=url;
}
</script>
</body>
</html>
During the start-up and operation of the project BUG And problem analysis
- STS Console “?” Symbol , As shown in the figure :
- Service startup failed , As shown in the figure :
- There are no errors in the template , As shown in the figure :
- Incorrect date format , As shown in the figure :
- On the page ${} Wrong content , As shown in the figure :
- Incorrect page date format , As shown in the figure :
- Dependency injection failed , As shown in the figure :
- Null pointer exception (NullPointerException), As shown in the figure :
405 The exception indicates that the request submitted by the client does not match the request that can be processed by the server
Product deletion business implementation
Business description
After inquiring the commodity information from the commodity storehouse , Click on the page to delete the hyperlink , be based on id Delete current line record
Business timing analysis
On the product presentation page , The user performs the delete operation , The deletion sequence is shown in the figure :
Dao Interface method and mapping definition
stay GoodsDao Interface defines the method of deleting goods and SQL mapping
@Delete("delete from tb_brand where id=#{id}")
int findGoods02(Integer id);
brand.html Add delete
<td><a th:href="@{/goods/doFind/{id}(id=@{g.id})}">delete</a></td>
Button mode
<td><button type="button" th:onclick="delectBy([[${g.id}]])"> Delete </button>
</td>
function delectBy(id){
if(!confirm(" Are you sure to delete ")) return;
location.href="http://localhost/goods/delectBy/"+id;
}
1)${} by thymeleaf For medium EL expression , Used from the server side model Get data in
2)th:each by thymeleaf Defined custom label properties , For iterative data .
3)th:text by thymeleaf Defined custom label properties , Used to set text content .
Service Interface method definition and implementation
stay GoodsService Add delete method to the interface , The code is as follows :
int findGoods02(Integer id);
stay GoodsService Implementation class of GoodsImp Add deleteById Method realization . The code is as follows .
@Override
public int findGoods02(Integer id) {
long t1=System.currentTimeMillis();
int rows=goodsDao.findGoods02(id);
long t2=System.currentTimeMillis();
log.info("find02->{}",t2-t1);
return rows;
}
Add to the implementation class doDeleteById Method , The code is as follows :
@GetMapping("/goods/delectBy/{id}")
public String delectBy(@PathVariable Integer id,Model model){
goodsService.findGoods02(id);
List<Goods> list=goodsService.findGoods(null);
model.addAttribute("list", list);
return "brand";
}
test : Normal operation is basically ok
@Test
void testwo(){
int rows=goodsService.findGoods02(10);
Assertions.assertNotEquals(-1, rows);
System.out.println(rows);
}
During project start-up and operation Bug And problem analysis
- SQL Mapping element definition problem , As shown in the figure :
- The client request parameters do not match the server parameters , As shown in the figure :
Product addition business implementation
Business description
stay Goods List page , Add add button , Add pages , Then enter the product information in the add page , Then save it to the database ,
Product add page , The design is as shown in the figure :
Business timing analysis
On the product add page , Enter product information , Then submit it to the server for saving , The timing analysis is shown in the figure :
Dao Interface method and mapping definition
stay GoodsDao Add an interface method for saving commodity information and SQL mapping , The code is as follows :
@Insert("insert into tb_goods(name,remark,createdTime)
values (#{name},#{remark},now())")
int insertObject(Goods entity);
explain : When SQL When the sentences are more complicated , Can also be SQL Define to mapping file (xml file ) in .
Service Interface method definition and implementation
stay GoodsService Add business methods to the interface , Used to add product information , The code is as follows :
int saveGoods(Goods entity);
stay GoodsSerivceImpl Class to add interface method implementation , The code is as follows :
@Override
public int saveGoods(Goods entity) {
int rows=goodsDao.insertObject(entity);
return rows;
}
Write a Good.html, To see if success is
as follows :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
<input type="button" onclick="doqu()" value=" Back to the home page ">
</form>
<h1> success </h1>
<script>
function doqu(){
var url="http://localhost/goods/doFind";
location.href=url;
}
</script>
</body>
</html>
Controller Object method definition and implementation
stay GoodsController Class to handle the product addition request , The code is as follows :
@RequestMapping("/goods/doAll")
public String doAll(Goods en){
goodsService.saveGoods(en);
return "Good";
}
stay GoodsController Class to return the product addition page , The code is as follows :
@GetMapping("/goods/doGoodsAddUI")
public String doGoodsAddUI() {
return "one";
}
Goods Add page design and Implementation
stay templates Of pages Add to catalog one.html page , The code is as follows
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css"> ul li {list-style-type: none;} </style>
</head>
<body>
<h1>The Goods Add Page</h1>
<form th:action="@{/goods/doAll}" method="post">
<ul>
<li>name:
<li><input type="text" name="name">
<li>remark:
<li><textarea rows="5" cols="50" name="remark"></textarea>
<li><input type="submit" value=" Submit ">
</ul>
</form>
</body>
</html>
stay brand.html Add... To the page , Hyperlinks can jump to add pages , The key codes are as follows :
<a th:href="@{/goods/doGoodsAddUI}"> Add the goods </a>
<!- Button jump -->
<td><button type="button" th:onclick="Allone()"> Add the goods </button>
<script>
function Allone(){
var url="http://localhost/goods/doGoodsAddUI";
location.href=url;
}
</script>
start-up Tomcat Server access test analysis
First step : start-up web The server , Check whether the startup process is OK, If there are no problems, go to the next step .
The second step : Open the browser and type in the address http://localhost/goods/doGood...), The following interface appears , As shown in the figure :
The third step : Fill in the form in the add page , And then click save Button to submit the form data to the server , As shown in the figure :
During project start-up and operation Bug And problem analysis
- Client display 400 abnormal , As shown in the figure :
- When saving 500 abnormal , As shown in the figure :
- Database integrity constraint exception , As shown in the figure :
Product modification business implementation
Business description
On the product list page , Click on update Options , Based on goods id Query the current row record and update it to goods-update page , As shown in the figure :
stay update Page selection , Modify product information , And then click update goods Submit the form data to the server for update
Business timing analysis
be based on id The timing design of query commodity information
take goods-update The data in the page is submitted to the server for update timing design
Dao Interface method and mapping definition
stay GoodsDao Based on id Methods for inquiring commodity information and SQL mapping , The code is as follows :
@Select("select * from tb_brand where id=#{id}")
Goods findById(Integer id);
stay GoodsDao Based on id perform Goods How to update products and SQL mapping , The code is as follows :
@Update("update tb_brand set name=#{name},remark=#{remark} where id=#{id}")
int updateGoods(Goods goods);
Service Interface method definition and implementation
stay GoodsService Based on id How to query and update product information , The code is as follows :
Goods findById(Integer id);
int updateGoods(Goods goods);
stay brand.html Add... To the page , Hyperlinks can jump to the modification page , The key codes are as follows :
<td><button type="button" th:onclick="updateone([[${g.id}]])"> modify </button>
<script>
function updateone(id){
if(!confirm(" Are you sure you want to change ")) return;
var url="http://localhost/goods/doFindBy/"+id;
location.href=url;
}
</script>
stay GoodsServiceImpl Based on id How to query and update product information , The code is as follows :
@Override
public Goods findById(Integer id) {
//.....
return goodsDao.findById(id);
}
@Override
public int updateGoods(Goods goods) {
return goodsDao.updateGoods(goods);
}
Controller Object method definition and implementation
stay GoodsController Based on id How to query product information , The code is as follows :
@GetMapping("/goods/doFindBy/{id}")
public String doFindBy(@PathVariable Integer id,Model model){
Goods goods=goodsService.findById(id);
model.addAttribute("goods",goods);
return "update";
}
stay GoodsController Add methods to update product information , The code is as follows :
@GetMapping("/goods/doUpdate")
public String doUpdategoods(Goods goods){
goodsService.updateGoods(goods);
return "Good";
}
Goods Modify page design and Implementation
stay templates Add to catalog update.html page , The code is designed as follows :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css"> ul li {list-style-type: none} </style>
</head>
<body>
<h1>The Goods Update Page</h1>
<form th:action="@{/goods/doUpdate}" method="get">
<input type="hidden" name="id" th:value="${goods.id}">
<ul>
<li>name:
<li><input type="text" name="name" th:value="${goods.name}">
<li>remark:
<li><textarea rows="3" cols="30" name="remark" th:text="${goods.remark}"></textarea>
<li><input type="submit" value=" Submit ">
</ul>
</form>
</body>
</html>
start-up Tomcat Service access test analysis
start-up tomcat service , Visit the product list page , As shown in the figure :
On the list page , Click on update Options , Go to the update page
Update the data in the form page , And then submit , Go to the list page to see the update results , As shown in the figure :