SpringBoot简单demo

1,656 阅读3分钟

传统前后端交互模式

步骤

  1. 创项目(建module)

  2. 导入依赖(改pom.xml)

  3. 改配置(application.yml)

  4. 创建项目结构(dao,service,controller)

  5. 写业务

6. 约定 > 配置 > 编码

创建项目

  1. 我使用的是Spring Initializr的方式,不用手写启动类,把这些通用配置勾选上,也可以创建传统maven项目,自己手写启动类,手动添加依赖。

image.png 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>
  1. 改配置文件
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.结构

image.png

业务实现

Controller

  1. @Controller注解:@Controller用于标记在一个类上,使用它标记的类就是一个SpringMvc Controller对象,分发处理器会扫描使用该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。@Controller只是定义了一个控制器类,而使用@RequestMapping注解的方法才是处理请求的处理器。可以指定一级路径
  2. @RestController注解:@Controller+@RequestBody 可以指定一级路径
  3. @RequestMapping注解:在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于servlet的web.xml中url配置。
  4. @GetMapping和@PostMapping都是基于@RequestMapping注解,不用配置请求方式。
  5. @RequestParam注解:将请求参数绑定到你Controller(控制层)的方法参数上,如果url上的参数名与value属性中的值一致可以不写value,但是参数的类型要对应。

image.png

  1. ModelAndView 模型视图对象,可以存相应的参数返回给前端,同时也可以指定下一个视图(页面)。
        name , value
        mv.addObject("userId",userId);
        mv.addObject("carts",cartsList);
        视图名称
        mv.setViewName("carts");
  1. PageHelper的使用:
// 当前页pageNum,页的大小pageSize(2)
PageHelper.startPage(pageNum, 2);
List<User> users = userService.listUser();
//导航页码数
PageInfo<User> pageInfo = new PageInfo<>(users,3);

Service

  1. @Service注解:作用在service业务逻辑层,默认按照名称进行装配到bean中,也可以使用该注解的那么属性进行指定
  2. @AutoWire注解:从bean中找到相应实例进行属性注入。
  3. @Transactional注解:配置事务,一般在service和dao层添加。默认仅对RuntimeException和 Error发生回滚。

dao层

  1. 首先要有sqlMapConfig.xml注解。
  2. 最好把mp实现不了的sql,写入相应mapoer的xml配置文件中,方便后期维护。

传统的thymeleaf模板

  1. 静态资源和页面一般在static和templates的包下,springboot默认情况
  2. 然后就是thymeleaf模板的一些语法··· 3. 注意在注释掉前端页面的时候,如果注释的部分没有标签包裹直接注释,会不生效,报错会提示你模板资源未找到,坑。 如:
当前第[[${pageInfo.pageNum}]]页,共[[${pageInfo.pages}]]页,共[[${pageInfo.total}]]条记录

模拟前后端分离

Controller

  1. 最好有二级路径 @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;
}
  1. @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);
    }
}

注意事项

  1. 在使用thymeleaf模板时要注意它的表达式,有些无法注释掉。

  2. ajax异步请求的写法,参数data和function(data),一个是路径方法的参数,另一个是方法返回值。

  3. 在拼接html标签是的格式(很麻烦)。

  4. 在使用ajax获取填充数据时,它的格式,它有几层封装。如:可能为data.object.list[i].id。