传统前后端交互模式
步骤
-
创项目(建module)
-
导入依赖(改pom.xml)
-
改配置(application.yml)
-
创建项目结构(dao,service,controller)
-
写业务
6. 约定 > 配置 > 编码
创建项目
- 我使用的是Spring Initializr的方式,不用手写启动类,把这些通用配置勾选上,也可以创建传统maven项目,自己手写启动类,手动添加依赖。
2.导入相关依赖,我使用了thymeleaf模板引擎,和一些数据库常用依赖(mp,pagehelper)
thymeleaf引擎
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency
mybatis-plus的springboot支持
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
- 改配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root
druid:
initial-size: 5
min-idle: 5
max-wait: 60000
mvc:
view:
prefix: /
suffix: .jsp
# thymeleaf:
# mode: HTML
# encoding: UTF-8
# servlet:
# content-type: text/html
# cache: false
# prefix: classpath:/templates/
# suffix: .html
使用mp需要配置mapper的路径,否则找不到对应的mapper
还要在启动类中加@MapperScan("com.hellojava.mapper") //扫描mapper这个包
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.hellojava.pojo
configuration:
map-underscore-to-camel-case: true
4.结构
业务实现
Controller
- @Controller注解:@Controller用于标记在一个类上,使用它标记的类就是一个SpringMvc Controller对象,分发处理器会扫描使用该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。@Controller只是定义了一个控制器类,而使用@RequestMapping注解的方法才是处理请求的处理器。可以指定一级路径
- @RestController注解:@Controller+@RequestBody 可以指定一级路径
- @RequestMapping注解:在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于servlet的web.xml中url配置。
- @GetMapping和@PostMapping都是基于@RequestMapping注解,不用配置请求方式。
- @RequestParam注解:将请求参数绑定到你Controller(控制层)的方法参数上,如果url上的参数名与value属性中的值一致可以不写value,但是参数的类型要对应。
- ModelAndView 模型视图对象,可以存相应的参数返回给前端,同时也可以指定下一个视图(页面)。
name , value
mv.addObject("userId",userId);
mv.addObject("carts",cartsList);
视图名称
mv.setViewName("carts");
- PageHelper的使用:
// 当前页pageNum,页的大小pageSize(2)
PageHelper.startPage(pageNum, 2);
List<User> users = userService.listUser();
//导航页码数
PageInfo<User> pageInfo = new PageInfo<>(users,3);
Service
- @Service注解:作用在service业务逻辑层,默认按照名称进行装配到bean中,也可以使用该注解的那么属性进行指定
- @AutoWire注解:从bean中找到相应实例进行属性注入。
- @Transactional注解:配置事务,一般在service和dao层添加。默认仅对RuntimeException和 Error发生回滚。
dao层
- 首先要有sqlMapConfig.xml注解。
- 最好把mp实现不了的sql,写入相应mapoer的xml配置文件中,方便后期维护。
传统的thymeleaf模板
- 静态资源和页面一般在static和templates的包下,springboot默认情况
- 然后就是thymeleaf模板的一些语法··· 3. 注意在注释掉前端页面的时候,如果注释的部分没有标签包裹直接注释,会不生效,报错会提示你模板资源未找到,坑。 如:
当前第[[${pageInfo.pageNum}]]页,共[[${pageInfo.pages}]]页,共[[${pageInfo.total}]]条记录
模拟前后端分离
Controller
- 最好有二级路径 @Controller("/user")
@PostMapping("/list")
/**
* 登录controller
* @param user
* @return
*/
@PostMapping("/login")
@ResponseBody
public User login(User user){
System.out.println(user);
User login = userService.login(user);
if (login != null) return login;
else return null;
}
- @ResponseBody注解:把返回结果封装成json数据。## FastJson(阿里)pojo类最好实现序列化接口。
Service和Dao
基本和前后端未分离一致。
ajax异步提交
在js块中编写
login.jsp
function login() {
$.ajax({
//提交方式
type: "POST",
//路径
url:"/user/login",
//序列化你表单中的值username:zhangsan,password:123,一般为参数
data:$('#userfrom').serialize(),// 你的formid
//function中的data表示后端return的数据
success: function(data) {
// console.log(111)
if (data.id != 0) {
var userId = data.id;
//页面控制台f12,打印出来进行测试校验
console.log(userId);
// alert(userId);
//把id加入到cookie中,方便之后获取
addcookie(userId);
//console.log(data.id);
//页面的跳转
window.location.href = "/showAllGoods.jsp";
}
else alert("error")
}
});
//添加cookie的方法
function addcookie(userId) {
var stringValue = userId;//需要存的数据
var oDate = new Date();
oDate.setTime(oDate.getTime() + 1 * 24 * 60 * 60 * 1000);//设置过期时间
//转成字符串
var cookieString = "UserId=" + stringValue + ";expires='" + oDate.toGMTString() + ";path=/";
document.cookie = cookieString;//存cookie
}
}
<form id="userfrom" method="post">
用户:<input name="username" type="text" value="username" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = '请输入...';}"><span>${loginError}</span>
密码:<input name="password" type="password" value="password" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'password';}">
<div class="forgot">
<input type="button" value="登陆" onclick="login()">
</div>
</form>
showAllGoods.jsp
//该方法页面加载后会自动执行
$(function(){
query();
});
//获取cookie
var userId = getCookie("UserId");
function getCookie(UserId){//获取指定名称的cookie的值
var arrStr = document.cookie.split("; ");
for (var i = 0; i < arrStr.length; i++) {
var temp = arrStr[i].split("=");
if (temp[0] == UserId){
return decodeURI(temp[1]);
}
}
}
//查询数据,未分页
function query() {
$.ajax({
type: "post",//提交方式
url: "/togoods1?userId="+userId, //请求地址
data: null, //携带的参数(地址栏拼参)
dataType: "json",
success: function callbackFun(data) {
//清空数据
//clearDate();
console.log(data[1].id);
console.log("11111");
console.log(userId);
//alert(data);
//查询数据
fillTable(data);
}
});
}
//填充数据,使用字符串拼接的方式,注意data的类型,不同类型获取值的方式不同如:data.object.list[i].id
function fillTable(data) {
var trs = "";//不初始化字符串"",会默认"undefined"
for (var i in data) {
// totalCount++;
var tr="<tr>"
+"<td>"+data[i].id+"</td>"
+"<td>"+data[i].goodsName+"</td>"
+"<td>"+data[i].price+"</td>"
+"<td>"+data[i].count+"</td>"
+"<td>"+data[i].goodsTime+"</td>"
+"<td><input type='button' name='addToChart' id='addToChart' value='加入购物车' onclick='addToChart("+data[i].id+")' />"
+"<td><input type='button' name='addgoodsStock' id='addgoodsStock' value='添加库存' onclick='addgoodsStock("+data[i].id+","+data[i].count+")' />"
+"</tr>";
trs += tr;
$("#t_body").html(trs);
}
// totalPageCount = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1);
}
//清空数据
function clearDate() {
$("#t_body").html("");
}
//var userId = "1";
function addToChart(goodsId) {
$.ajax({
type: "post",//提交方式
url: "/addToCarts2", //请求地址
data: {userId:userId,goodsId:goodsId}, //携带的参数(地址栏拼参)
success: function (msg) { //成功回调函数 msg ---返回的内容
/* alert(msg); */
if (msg == "success") {
alert(userId);
// $("#" + userid).html();
window.location.reload();
}
}
});
}
function addgoodsStock(goodsId,count) {
$.ajax({
type: "post",//提交方式
url: "/addgoodsStock2?goodsId=" + goodsId +"&count=" + count, //请求地址
data: null, //携带的参数(地址栏拼参)
success: function (msg) { //成功回调函数 msg ---返回的内容
/* alert(msg); */
if (msg == "success") {
//$("#tr_"+userid).html("");
window.location.reload();
}
}
});
}
function tocart(userId) {
$.ajax({
type: "post",//提交方式
url: "/tocart?userId="+userId, //请求地址
data: null, //携带的参数(地址栏拼参)
success: function (msg) { //成功回调函数 msg ---返回的内容
/* alert(msg); */
if (msg == "success") {
//$("#tr_"+userid).html("");
window.location.href = "/showCart.jsp";
}
}
});
}
<table id="dataList"
class="table table-bordered table-striped table-hover dataTable">
<thead>
<tr>
<th class="sorting_asc">编号</th>
<th class="sorting_desc">商品名</th>
<th class="sorting_desc">价格</th>
<th class="sorting_desc">库存</th>
<th class="sorting_desc">创建时间</th>
<th class="sorting">操作</th>
</tr>
</thead>
<tbody id="t_body">
</tbody>
<td><button onclick="tocart(userId)">去购物车</button></td>
</table>
showCart.jsp
与showAllGoods类似。
/**
* 删除一个
* @param userId
* @param goodsId
* @param count
* @return
*/
@PostMapping("deleteOneToChart")
@ResponseBody
public String deleteOneToChart(@RequestParam("userId") Integer userId,
@RequestParam("goodsId")Integer goodsId,
@RequestParam(value = "count") Integer count
){
System.out.println(count);
List<Carts> cartsList = cartsService.deleteOneCount(userId, goodsId,count);
System.out.println(userId);
return "success";
}
function deleteOneToChart(goodsId,count) {
$.ajax({
type: "post",//提交方式
url: "/deleteOneToChart?userId=" + userId +"&goodsId=" + goodsId + "&count=" + count, //请求地址
data: null, //携带的参数(地址栏拼参)
success: function (msg) { //成功回调函数 msg ---返回的内容
/* alert(msg); */
if (msg == "success") {
//$("#tr_"+userid).html("");
alert("删除成功");
window.location.reload();
}
}
});
}
//填充数据
function fillTable(data) {
var trs = "";//不初始化字符串"",会默认"undefined"
for (var i in data) {
// totalCount++;
var tr="<tr>"
+"<td>"+data[i].goods.goodsName+"</td>"
+"<td>"+data[i].count+"</td>"
+"<td>"+data[i].goods.price+"</td>"
+"<td>"+(data[i].count)*(data[i].goods.price)+"</td>"
+"<td><input type='button' name='addToChart' id='addToChart' value='清空该商品' onclick='deleteToChart("+data[i].goods.id+")' />"
+"<td><input type='button' name='addgoodsStock' id='addgoodsStock' value='减少一个' onclick='deleteOneToChart("+data[i].goods.id+","+data[i].count+")' />"
+"</tr>";
trs += tr;
$("#t_body").html(trs);
}
}
注意事项
-
在使用thymeleaf模板时要注意它的表达式,有些无法注释掉。
-
ajax异步请求的写法,参数data和function(data),一个是路径方法的参数,另一个是方法返回值。
-
在拼接html标签是的格式(很麻烦)。
-
在使用ajax获取填充数据时,它的格式,它有几层封装。如:可能为data.object.list[i].id。