how2j.cn


39分59秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)

步骤 1 : IDEA 版本问题   
步骤 2 : 先运行,看到效果,再学习   
步骤 3 : 模仿和排错   
步骤 4 : 新建项目   
步骤 5 : 选中maven webapp格式   
步骤 6 : 项目参数   
步骤 7 : 依赖   
步骤 8 : 项目路径   
步骤 9 : Maven仓库   
步骤 10 : maven项目启动缓慢   
步骤 11 : 删除 TmallSpringbootApplication.java   
步骤 12 : pom.xml   
步骤 13 : Category.java   
步骤 14 : CategoryDAO.java   
步骤 15 : CategoryService.java   
步骤 16 : AdminPageController.java   
步骤 17 : CategoryController.java   
步骤 18 : Application.java   
步骤 19 : CORSConfiguration.java   
步骤 20 : GloabalExceptionHandler.java   
步骤 21 : TestTmall 测试数据   
步骤 22 : application.properties   
步骤 23 : 静态资源   
步骤 24 : listCategory.html   
步骤 25 : vue-cli   
步骤 26 : 测试地址   
步骤 27 : 可运行项目   
步骤 28 : 思路图   
步骤 29 : Redis,ElasticSearch 和 Shiro   
步骤 30 : 热部署问题   

步骤 1 :

IDEA 版本问题

注: IDEA 必须使用 IDEA 2017, 2018版本有BUG,无法部署本项目
如果一定要用idea 2018, 需要做如下修改:
File->Settings->Build,Execution,Deployment->Build Tools->Maven->Importing 取消 "Store generated project files externally"
这样才能用
步骤 2 :

先运行,看到效果,再学习

接下来就开始一步一步来,由浅入深地开发功能了。

因为项目用到了Springboot技术,Springboot 技术本身较为复杂,涉及到了多个框架、多个类、多个配置文件。 不仅如此,模仿天猫业务也较为复杂,所以在进行项目开发之前,一定要先按照 可运行的项目的指导,先下载右上角的可运行项目,配置运行起来, 先自己跑起来,确认项目本身没有问题,建立对学习内容的信心,然后再跟着步骤,一步步做出来。

十分不推荐一来就跟着步骤做下去,本知识点一共有20多个步骤,只要任何一个步骤,跟着做的时候写错了,都有可能导致项目无法成功启动,影响学习情绪和学习效果。 所以一定要先按照 可运行的项目的指导,先下载右上角的可运行项目,配置运行起来,成功跑起来,然后再照着教程,一个一个地做下去,这样出了问题心里才有底,通过代码比较等手段,定位到问题所在,成功消化掉这个知识点。
步骤 3 :

模仿和排错

在确保可运行项目能够正确无误地运行之后,再严格照着教程的步骤,对代码模仿一遍。
模仿过程难免代码有出入,导致无法得到期望的运行结果,此时此刻通过比较正确答案 ( 可运行项目 ) 和自己的代码,来定位问题所在。
采用这种方式,学习有效果,排错有效率,可以较为明显地提升学习速度,跨过学习路上的各个槛。

推荐使用diffmerge软件,进行文件夹比较。把你自己做的项目文件夹,和我的可运行项目文件夹进行比较。
这个软件很牛逼的,可以知道文件夹里哪两个文件不对,并且很明显地标记出来
这里提供了绿色安装和使用教程:diffmerge 下载和使用教程
步骤 4 :

新建项目

点击Create New Project新建项目
新建项目
步骤 5 :

选中maven webapp格式

1. 左边选中Spring Initializr
2. Next
选中maven webapp格式
步骤 6 :

项目参数

GroupId: com.how2java.tmall
ArtifactId: tmall_springboot
项目参数
步骤 7 :

依赖

1. 左边选中 Web
2. 右边选中 Web
依赖
步骤 8 :

项目路径

项目路径选择

e:\project\tmall_springboot

然后点Finish
项目路径
步骤 9 :

Maven仓库

天猫springboot项目会用到一系列的jar包,在右上角的.m2.rar 只有64m,里面包含了这个项目用到的jar包。 解压出来后,放在maven的仓库目录里。

通常来讲,maven 仓库的默认目录是:${user.home}/.m2/repository。
对应我的机器就是

C:\Users\X7TI\.m2\repository

把这些jar包复制进去,否则导入项目的时候,就要自己从网站上下载,会很花费时间的
步骤 10 :

maven项目启动缓慢

此时用的maven配置是idea自带的maven,默认仓库地址也是国外的,所以在启动maven项目的时候会比较卡。 解决办法请点击:idea 启动maven项目缓慢的解决办法
步骤 11 :

删除 TmallSpringbootApplication.java

首先删除 TmallSpringbootApplication.java 这个自动创建的类,并且把其包也删除掉。
删除掉后,就是如图所示的光秃秃的样子~
删除 TmallSpringbootApplication.java
步骤 12 :

pom.xml

复制如下内容到已经存在的pom里,如图所示,这个过程会导致idea去下载pom里声明的相关jar包,会花一定的时间,视网络和计算机性能而定。
此时会弹出如图所示的提醒,为了避免每次修改 pom.xml 都出现这个对话框,点击 "Enable Auto-Import"
为了确保导入成功,右键点击pom.xml->Maven->Reimport
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.how2java.tmall</groupId> <artifactId>tmall_springboot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>tmall_springboot</name> <description>tmall_springboot</description> <packaging>war</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <!-- springboot web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springboot tomcat 支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- 热部署 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- jpa--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- springboot test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- elastic search --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!-- 用了 elasticsearch 就要加这么一个,不然要com.sun.jna.Native 错误 --> <dependency> <groupId>com.sun.jna</groupId> <artifactId>jna</artifactId> <version>3.0.9</version> </dependency> <!-- thymeleaf legacyhtml5 模式支持 --> <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> <version>1.9.22</version> </dependency> <!-- 测试支持 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- tomcat的支持.--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>8.5.23</version> </dependency> <!-- mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version> 4.12</version> </dependency> <!-- commons-lang --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!-- hsqldb --> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
步骤 13 :

Category.java

首先新建包,菜单 -> File -> Package -> 然后输入

com.how2java.tmall.pojo

然后创建类 Category,接下来.讲解这个类。

@Entity

表示这是一个实体类

@Table(name = "category")

表示对应的表名是 category

@JsonIgnoreProperties({ "handler","hibernateLazyInitializer" })

因为是做前后端分离,而前后端数据交互用的是 json 格式。 那么 Category 对象就会被转换为 json 数据。 而本项目使用 jpa 来做实体类的持久化,jpa 默认会使用 hibernate, 在 jpa 工作过程中,就会创造代理类来继承 Category ,并添加 handler 和 hibernateLazyInitializer 这两个无须 json 化的属性,所以这里需要用 JsonIgnoreProperties 把这两个属性忽略掉。
Category.java
package com.how2java.tmall.pojo; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @Entity @Table(name = "category") @JsonIgnoreProperties({ "handler","hibernateLazyInitializer" }) public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") int id; String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
步骤 14 :

CategoryDAO.java

Category.java 步骤里已经讲解过了如何创建包,这里就不讲解如何创建包,而是直接给出类了。
CategoryDAO 类集成了 JpaRepository,就提供了CRUD和分页 的各种常见功能。 这就是采用 JPA 方便的地方~
package com.how2java.tmall.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.how2java.tmall.pojo.Category; public interface CategoryDAO extends JpaRepository<Category,Integer>{ }
package com.how2java.tmall.dao;
 
import org.springframework.data.jpa.repository.JpaRepository;

import com.how2java.tmall.pojo.Category;

public interface CategoryDAO extends JpaRepository<Category,Integer>{

}
步骤 15 :

CategoryService.java


@Service

标记这个类是 Service类

@Autowired CategoryDAO categoryDAO;

自动装配 上个步骤的 CategoryDAO 对象

public List<Category> list() {
Sort sort = new Sort(Sort.Direction.DESC, "id");
return categoryDAO.findAll(sort);
}

首先创建一个 Sort 对象,表示通过 id 到排序, 然后通过 categoryDAO进行查询。

注: 这里抛弃了 CategoryService 接口 加上 CategoryService 实现类的这种累赘的写法,而是直接使用 CategoryService 作为实现类来做。
package com.how2java.tmall.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import com.how2java.tmall.dao.CategoryDAO; import com.how2java.tmall.pojo.Category; @Service public class CategoryService { @Autowired CategoryDAO categoryDAO; public List<Category> list() { Sort sort = new Sort(Sort.Direction.DESC, "id"); return categoryDAO.findAll(sort); } }
package com.how2java.tmall.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import com.how2java.tmall.dao.CategoryDAO;
import com.how2java.tmall.pojo.Category;

@Service
public class CategoryService {
	@Autowired CategoryDAO categoryDAO;

	public List<Category> list() {
    	Sort sort = new Sort(Sort.Direction.DESC, "id");
		return categoryDAO.findAll(sort);
	}
}
步骤 16 :

AdminPageController.java

后台管理页面跳转专用控制器。
因为是做前后端分离,所以数据是通过 RESTFUL接口来取的,而在业务上,除了 RESTFUL 服务要提供,还要提供页面跳转服务,所以所有的后台页面跳转都放在 AdminPageController 这个控制器里。 而RSTFUL 专门放在 Category 对应的控制器 CategoryController.java 里面。 这样代码更清晰,不会搅起搅起的~

@Controller

表示这是一个控制器。

@GetMapping(value="/admin")
public String admin(){
return "redirect:admin_category_list";
}

访问地址 admin,就会客户端跳转到 admin_category_list去。

@GetMapping(value="/admin_category_list")
public String listCategory(){
return "admin/listCategory";
}

访问地址 admin_category_list 就会访问 admin/listCategory.html 文件。
package com.how2java.tmall.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class AdminPageController { @GetMapping(value="/admin") public String admin(){ return "redirect:admin_category_list"; } @GetMapping(value="/admin_category_list") public String listCategory(){ return "admin/listCategory"; } }
package com.how2java.tmall.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class AdminPageController {
	@GetMapping(value="/admin")
    public String admin(){
		return "redirect:admin_category_list";
    }
	@GetMapping(value="/admin_category_list")
	public String listCategory(){
		return "admin/listCategory";
	}
}
步骤 17 :

CategoryController.java

这个就是专门用来提供 RESTFUL 服务其控制器了

@RestController

表示这是一个控制器,并且对每个方法的返回值都会直接转换为 json 数据格式。

@Autowired CategoryService categoryService;

自动装配 CategoryService

@GetMapping("/categories")
public List<Category> list() throws Exception {
return categoryService.list();
}

对于categories 访问,会获取所有的 Category对象集合,并返回这个集合。 因为是声明为 @RestController, 所以这个集合,又会被自动转换为 JSON数组抛给浏览器。
package com.how2java.tmall.web; import com.how2java.tmall.pojo.Category; import com.how2java.tmall.service.CategoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class CategoryController { @Autowired CategoryService categoryService; @GetMapping("/categories") public List<Category> list() throws Exception { return categoryService.list(); } }
package com.how2java.tmall.web;

import com.how2java.tmall.pojo.Category;
import com.how2java.tmall.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
 
@RestController
public class CategoryController {
	@Autowired CategoryService categoryService;
    
	@GetMapping("/categories")
    public List<Category> list() throws Exception {
    	return categoryService.list();
    }
}

步骤 18 :

Application.java

启动类,代替自动生成的 TmallSpringbootApplication.java
package com.how2java.tmall; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
package com.how2java.tmall;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; 
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);    	
    }
}
步骤 19 :

CORSConfiguration.java

配置类,用于允许所有的请求都跨域。
因为是二次请求,第一次是获取 html 页面, 第二次通过 html 页面上的 js 代码异步获取数据,一旦部署到服务器就容易面临跨域请求问题,所以允许所有访问都跨域,就不会出现通过 ajax 获取数据获取不到的问题了。
package com.how2java.tmall.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class CORSConfiguration extends WebMvcConfigurerAdapter{ @Override public void addCorsMappings(CorsRegistry registry) { //所有请求都允许跨域 registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*"); } }
package com.how2java.tmall.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class CORSConfiguration extends WebMvcConfigurerAdapter{
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		//所有请求都允许跨域
		registry.addMapping("/**")
				.allowedOrigins("*")
				.allowedMethods("*")
				.allowedHeaders("*");
	}
}
步骤 20 :

GloabalExceptionHandler.java

异常处理,主要是在处理删除父类信息的时候,因为外键约束的存在,而导致违反约束。
package com.how2java.tmall.exception; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestController; @RestController @ControllerAdvice public class GloabalExceptionHandler { @ExceptionHandler(value = Exception.class) public String defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { e.printStackTrace(); Class constraintViolationException = Class.forName("org.hibernate.exception.ConstraintViolationException"); if(null!=e.getCause() && constraintViolationException==e.getCause().getClass()) { return "违反了约束,多半是外键约束"; } return e.getMessage(); } }
步骤 21 :

TestTmall 测试数据

刚开始用的时候,数据库里是没有数据的。 这里使用 简单的 jdbc 代码插入10条数据。
注: 既然是Springboot 教程,为什么不用 jpa 创建测试数据,而要用JDBC创建? 因为增加功能要到下个知识点才讲啊。。。
TestTmall 测试数据
package com.how2java.tmall.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TestTmall { public static void main(String args[]){ //准备分类测试数据: try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } try ( Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/tmall_springboot?useUnicode=true&characterEncoding=utf8", "root", "admin"); Statement s = c.createStatement(); ) { for (int i = 1; i <=10 ; i++) { String sqlFormat = "insert into category values (null, '测试分类%d')"; String sql = String.format(sqlFormat, i); s.execute(sql); } System.out.println("已经成功创建10条分类测试数据"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
步骤 22 :

application.properties

springboot 配置文件,有些项目会用 application.yml ,站长习惯用 .properties ,觉得更易读。
下面是配置文件的内容:

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tmall_springboot?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto = none

分别是数据库访问地址,账号密码,驱动以及表结构自动生成策略(none)。


spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

使用 thymeleaf 作为视图,这个是springboot 官方推荐视图,它的好处是可以是纯 html 。
其中LEGACYHTML5表示经典html5模式,即允许非严格的html出现,元素少点什么也可以编译通过, 这个比较符合大家的编写习惯,太过严格的html,写起来累。
cache=false 表示不要缓存,以免在开发过程中因为停留在缓存而给开发人员带来困扰。


server.context-path=/tmall_springboot

上下文地址为 tmall_springboot, 所以访问的时候,都要加上这个,比如:

http://127.0.0.1:8080/tmall_springboot/admin



spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb

设置上传文件大小,默认只有1 m


spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

jpa对实体类的默认字段会把驼峰命名的属性,转换为字段名的时候自动加上下划线。 这个配置的作用就是去掉下划线
比如属性名称是 createDate, jpa 默认转换为字段名 create_Date。 有了这个配置之后,就会转换为同名字段 createDate


spring.jpa.show-sql=true

显示 hibernate 执行的sql语句。 这个在上线之后,应该是关掉的,因为大量的 控制台输出会严重影响系统性能。 但是呢,因为本项目会和 redis 和 es 整合,打印 sql 语句的目的是为了观察 缓存是否起效果。
application.properties
#database spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tmall_springboot?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=admin spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.hibernate.ddl-auto = none #thymeleaf spring.thymeleaf.mode=LEGACYHTML5 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false #context server.context-path=/tmall_springboot #设置上传文件大小,默认只有1 m spring.http.multipart.maxFileSize=100Mb spring.http.multipart.maxRequestSize=100Mb spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #显示 hibernate运行的 sql 语句 spring.jpa.show-sql=true
步骤 23 :

静态资源

接下来是各种静态资源,诸如jquery, bootstrap, css, 图片,公用 html 等,内容稍杂,就不挨个列出来了。
这些静态资源打包在webapp.rar 里,被包含的文件打包在 include.rar里,放在右上角供下载,下载后解压即可,解压之后应该看到多出来如图所示的几个目录。

1. css,img,js目录是样式,图片脚本等文件
2. include/admin目录下是4个HTML 包含关系中讲解到的被包含文件

注: 如果目录不存在,比如 webapp目录, templates 目录不存在,请自行创建。
注: 静态资源为什么不放在 static 目录下? 一般说来,在约定里,springboot 的静态资源会在 static 目录下,但是我们是放在 webapp 目录下,为什么会这样呢? 因为我们还要做上传图片的功能,如果是放在 static 下,上传后的图片就无法被访问,还是放在 webapp 下,上传后,能够立即被访问。
静态资源
步骤 24 :

listCategory.html

接着在 templates 下面新建 admin目录,然后新建 listCategory.html 文件。
listCategory.html 看着复杂,其实没那么复杂,它其实就了两件事: 获取数据 和 展示数据
1. 获取数据

$(function(){
}

这个是jquery的代码,表示当整个html加载好了之后执行

var data4Vue = {
uri:'categories',
beans: []
};

vue用到的数据, uri表示访问哪个地址去获取数据,这里的值是 categories,和 CategoryController.java 相呼应


var vue = new Vue({
el: '#workingArea',
data: data4Vue,

创建Vue对象,el 表示和本页面的 <div id="workingArea" > 元素绑定,data 表示vue 使用上面的data4Vue对象。

mounted:function(){
this.list();
},

加载Vue对象成功之后会调用,成功的时候去调用 list() 函数。


methods: {
list:function(){
var url = this.uri;
axios.get(url).then(function(response) {
vue.beans = response.data;
});
}
}

list 函数使用 data4Vue里的 uri作为地址,然后调用 axios.js 这个 ajax库,进行异步调用。 调用成功之后,把服务端返回的数据,保存在 vue.beans 上。

2. 展示数据

<tr v-for="bean in beans ">

使用 v-for进行遍历, 这个 beans 就表示data4Vue里面的beans属性。

<td>{{bean.id}}</td>

bean就是遍历出来的每个id, 这里就是输出每个分类的id.

<a :href="'admin_property_list?cid=' + bean.id "><span class="glyphicon glyphicon-th-list"></span></a>

在超链里的href里拼接分类id.

如果不熟悉 Vue的用法,请学习 Vue.js 系列教材
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:include="include/admin/adminHeader::html('分类管理')" ></head> <body> <div th:replace="include/admin/adminNavigator::html" ></div> <script> $(function(){ var data4Vue = { uri:'categories', beans: [] }; //ViewModel var vue = new Vue({ el: '#workingArea', data: data4Vue, mounted:function(){ //mounted 表示这个 Vue 对象加载成功了 this.list(); }, methods: { list:function(){ var url = this.uri; axios.get(url).then(function(response) { vue.beans = response.data; }); } } }); }); </script> <div id="workingArea" > <h1 class="label label-info" >分类管理</h1> <br> <br> <div class="listDataTableDiv"> <table class="table table-striped table-bordered table-hover table-condensed"> <thead> <tr class="success"> <th>ID</th> <th>图片</th> <th>分类名称</th> <th>属性管理</th> <th>产品管理</th> <th>编辑</th> <th>删除</th> </tr> </thead> <tbody> <tr v-for="bean in beans "> <td>{{bean.id}}</td> <td> <img height="40px" :src="'img/category/'+bean.id+'.jpg'"> </td> <td> {{bean.name}} </td> <td> <a :href="'admin_property_list?cid=' + bean.id "><span class="glyphicon glyphicon-th-list"></span></a> </td> <td> <a :href="'admin_product_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a> </td> <td> <a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a> </td> <td> <a href="#nowhere" @click="deleteBean(bean.id)"><span class=" glyphicon glyphicon-trash"></span></a> </td> </tr> </tbody> </table> </div> </div> <div th:replace="include/admin/adminFooter::html" ></div> </body> </html>
步骤 25 :

vue-cli

本站提供了 node.js webpack 和vue-cli的教程。
vue-cli
webpack
node.js
但是为什么项目里不使用 vue-cli 呢?
因为几个原因
1. vue-cli 更适合做单页面开发,本项目是复杂的多页面。 为了使得 vue-cli 支持多页面,需要做很复杂的风险高的配置工作。
2. 版本原因。 webpack 有一个深受广大开发人员诟病的地方,就是其不同版本之间的兼容性有非常大的问题,很多不同版本之间完全不考虑兼容性,新版本直接就不能使用了。 比如本项目,假设我采用 vue-cli+webpack 进行开发,也许项目做出来一个月之内还是可以使用的。 但是这些工具一旦发生了更新,很有可能因为兼容性问题,大家就完全无法跟着教程做出一样的效果来了。 当一个教程,无法导致确定的学习效果,大家也就没有办法从这个教程上学到东西了,因为根本跑不通~~~

所以为了规避学习过程中的风险,本项目放弃了 vue-cli + webpack 的风格。(虽然当初花了很多时间做 vue-cli 和 webpack 等等教程。。。现在想想,真是有点天真呀,哈哈)。

虽然没有用 vue-cli 来做,也就是说,项目没有创建 .vue 这样的文件,但是项目中对 vue 的使用依然是其核心使用方式,一旦掌握了项目中的这些处理技巧和经验, 切换到 vue-cli 上做,也是很容易的,所以不要担心因为 没有用 vue-cli 而感觉损失了很大~
步骤 26 :

测试地址

访问如下测试地址:

http://localhost:8080/tmall_springboot/admin
测试地址
步骤 27 :

可运行项目

在右上角有本知识点对应的可运行项目下载 ,实在自己搞不出来,就下载解压出来比较一下。
步骤 28 :

思路图

1. 首先浏览器上访问路径 /admin
2. 这个路径被 AdminPageController 的admin方法匹配,然后客户端跳转到 admin_category_list
3. admin_category_list 被 AdminPageController 的 listCategory 方法匹配,服务端跳转到 admin/listCategory.html
4. listCategory.html 这个html页面通过http协议传输到浏览器端
5. 浏览器根据html 上的js代码,异步调用 categories 这个地址。 CategoryController 获取捕捉到这个请求,到数据库里查出所有的分类数据,并转换为 json数组返回给浏览器。
6. 浏览器根据这个json数组,通过 vue 的v-for 方式把其遍历到 多个 tr 元素上,用户就看到了表格里的多条数据了。
思路图
步骤 29 :

Redis,ElasticSearch 和 Shiro

关于 Redis, ES (ElasticSearch) 和 Shiro 的支持,会放在后面专门来做。
这样做的好处是什么呢? 先做不支持 Redis, ES 和 Shiro 的功能,然后再在这个基础上进行改造,这样就可以很清楚的明白二者的区别。 比起以来就什么都上,脉络更清晰,更容易掌握,理解和消化。
步骤 30 :

热部署问题

在idea里,修改了html和java,需要重启springboot 才能看到效果。
为了解决这个问题专门提供了解决方案:
在 idea2017 里 springboot thymeleaf 修改 html 之后不能立即看到效果的解决办法

eclipse 没有这个问题。。。


HOW2J公众号,关注后实时获知布最新的教程和优惠活动,谢谢。


问答区域    
2018-11-05 在这个环节,最后没有出现站长教程里出现的表格,如图所示
huangruihhu



在这个环节,最后没有出现站长教程里出现的表格,如图所示

							

							


2 个答案

how2j 答案时间:2018-11-06
/抱拳

huangruihhu 答案时间:2018-11-05
知道问题所在了,需要先运行步骤21,把测试数据插入进去




答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2018-11-05 一个小问题
我真的爱学习和思考
我想问 listCategory.html 文件源码里的vue里面的list()方法,那个vue.beans=respone.data,为什么不能用this.beans=respone.data?




2 个答案

我真的爱学习和思考 答案时间:2018-11-05
明白了,谢谢站长

how2j 答案时间:2018-11-05
如果此时写 this, 这个 this 就代表 axios function函数,而非你期望的 vue对象了
axios.get(url).then(function(response) {
            vue.beans = response.data;
        });




答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2018-11-02 这个
2018-10-30 导入右上角项目运行不报错,但是访问不了前端页面???




提问之前请登陆
关于 实践项目-天猫整站Springboot-查询 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 902680467
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: http://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图