赞
踩
目录
- @RestController
- public class IndexController {
-
- @GetMapping("/index")
- public String index(){
- return "欢迎访问首页";
- }
- }
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-devtools</artifactId>
- <optional>true</optional>
- </dependency>
- spring:
- devtools:
- restart:
- enabled: true #热部署生效
- additional-paths: src/main/java #设置重启目录
- exclude: static/** #设置classpath目录下的WEB-INF文件夹内容修改不重启
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- @Controller
- public class IndexController {
-
- @GetMapping("/index")
- public String index(ModelMap map){
- map.addAttribute("name","张三");
- return "index";
- }
- }
- @RestController
- public class IndexController {
-
- @GetMapping("/user")
- public User getUser(){
- User user = new User();
- user.setUsername("张三");
- user.setPassword("123");
- return user;
- }
- }
- @RestController
- public class IndexController {
-
- // http://localhost:8888/index?nickname=zhangsan
- @GetMapping("/index")
- public String index(@RequestParam("nickname") String name){
- return "你好"+name;
- }
- }
- @RestController
- public class IndexController {
-
- // http://localhost:8888/index?nickname=zhangsan
- @GetMapping("/index")
- public String index(String nickname){
- return "你好"+nickname;
- }
- }
- @RestController
- public class IndexController {
-
- // http://localhost:8888/index?nickname=zhangsan&phone=123
- @GetMapping("/index")
- public String index(String name,String phone){
- return "你好"+name+phone;
- }
- }
- @GetMapping("/getUser/{id}")
- public String getUser(@PathVariable String id){
- System.out.println("id->"+id);
- return "getUser";
- }
- // http://localhost:8888/getUser
- @PostMapping("/getUser")
- public String getUser(@RequestBody User user){
- System.out.println(user);
- return "getUser";
- }
- spring:
- mvc:
- static-path-pattern: /static/**
- web:
- resources:
- static-locations: classpath:/static/ #静态资源
SpringBoot实现文件上传功能
Springboot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1MB,单次请求的文件的总数不能大于10MB。
要更改这个默认值需要在配置文件application.yml中加入两个配置:
- spring:
- servlet:
- multipart:
- max-file-size: 10GB #文化最大10G
- max-request-size: 10GB #单次请求文件总数不能超过10G
当表单的enctype="multipart/form-data"时,可以使用MultipartFile获取上传的文件数据,再通过transferTo方法将其写入磁盘中:
- @RestController
- public class FileController {
-
- /**
- * 默认定位到的当前用户目录("user.dir")(即工程根目录)
- * JVM就可以据"user.dir" + "你自己设置的目录" 得到完整的路径(即绝对路径)
- */
-
- // private static final String UPLOADED_FOLDER = System.getProperty("user.dir")+"/upload/";
-
- @PostMapping("/upload")
- public String upload(MultipartFile file, HttpServletRequest request)throws Exception{
-
- System.out.println("文件大小:"+file.getSize());
- System.out.println("文件的ContentType:"+file.getContentType());
- System.out.println("文件的初始名字:"+file.getOriginalFilename());
-
- String path = request.getServletContext().getRealPath("/upload/");
- System.out.println("获取web服务器的运行目录:"+path);
- saveFile(file,path);
- return "upload success";
- }
-
- public void saveFile(MultipartFile f,String path)throws IOException{
- File upDir = new File(path);
- if (!upDir.exists()){
- upDir.mkdir();
- }
- File file = new File(path+f.getOriginalFilename());
- f.transferTo(file);
- }
- }

- public class LoginInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("LoginInterceptor");
- return true;
- }
- }
- @Configuration // Configuration必须要添加
- public class WebConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new LoginInterceptor());
- // registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**"); // 拦截所有user下面的接口
- }
- }
RESTful是目前流行的互联网软件服务架构设计风格。
REST(Representational State Transfer,表述性状态转移) 一词是由Roy Thomas Fielding在2000年的博士论文中提出的,它定义了互联网软件服务的架构原则,如果一个架构符合REST原则,则称之为RESTful架构。
REST并不是一个标准,它更像一组客户端和服务端交互时的架构理念和设计原则,基于这种架构理念和设计原则的Web API更加简洁、更有层次。
HTTP Method | 接口地址 | 接口描述 |
---|---|---|
POST | /user | 创建用户 |
GET | /user/id | 根据id获取用户信息 |
PUT | /user | 更新用户 |
DELETE | /user/id | 根据id删除对应用户 |
- @RestController
- public class UserController {
-
- // @PathVariable:注:路由内属性与形参相同可简写,
- // 若不相同,则需要加上对应的名称绑定,如:@PathVariable("id")
-
- @GetMapping("/user/{id}")
- public String getUserById(@PathVariable int id){
- System.out.println(id);
- return "根据ID获取用户信息";
- }
-
- @PostMapping("/user")
- public String save(User user){
- return "添加用户";
- }
-
- @PutMapping("/user")
- public String update(User user){
- return "更新用户";
- }
-
- @DeleteMapping("/user/{id}")
- public String deleteById(@PathVariable int id){
- System.out.println(id);
- return "根据id删除用户";
- }
- }

- <!-- swagger -->
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger2</artifactId>
- <version>2.9.2</version>
- </dependency>
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-swagger-ui</artifactId>
- <version>2.9.2</version>
- </dependency>
- @Configuration // 告诉spring容器,这个类是一个配置类
- @EnableSwagger2 // 启用Swagger2功能
- public class Swagger2Config {
-
- @Bean
- public Docket createRestApi(){
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- // com包下的所有API都交给Swagger2管理
- .apis(RequestHandlerSelectors.basePackage("com"))
- .paths(PathSelectors.any())
- .build();
- }
-
- // API文档页面显示信息
- private ApiInfo apiInfo(){
- return new ApiInfoBuilder()
- .title("文件系统项目API") // 标题
- .description("学习Springboot+Vue项目") // 描述
- .build();
- }
- }

- # yml文件:
- mvc:
- pathmatch:
- matching-strategy: ant_path_matcher
-
- # properties文件:
- spring.mvc.pathmatch.matching-strategy=ant_path_matcher
- <!-- mybatisPlus 依赖 -->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.2</version>
- </dependency>
- <!-- mysql驱动依赖 -->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
- <!-- 数据库连接池Druid -->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid-spring-boot-starter</artifactId>
- <version>1.2.13-SNSAPSHOT</version>
- </dependency>

- spring:
- datasource:
- type: com.alibaba.druid.pool.DruidDataSource
- driver-class-name: com.mysql.jdbc.Driver
- url: jdbc:mysql://localhost:3306/mydb?useSSL=false
- username: root
- password: 646681
- mybatis-plus:
- configuration:
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- @Mapper
- public interface UserMapper {
-
- // 增加用户
- @Insert("insert into user(username,password,birthday) values (#{username},#{password},#{birthday})")
- int add(User user);
-
- // 根据id删除用户
- @Delete("delete from user where id=#{id}")
- int delete(int id);
-
- // 更新用户信息
- @Update("update user set username=#{username},password=#{password},birthday=#{birthday} where id=#{id}")
- int update(User user);
-
- // 根据id查询用户
- @Select("select * from user where id=#{id}")
- User findById(int id);
-
- // 查询所有用户
- @Select("select * from user")
- List<User> findAll();
-
- }

- @Mapper
- public interface UserMapper extends BaseMapper<User> {
-
- }
要操作User对象,就将User传给BaseMapper
BaseMapper中提供了很多操作,如增删改查等等。
直接调用查询方法即可,如需知道更多方法的操作使用,请到Mybatis-Plus官网查看
- @TableName("t_user")
- public class User {
-
- @TableId(type = IdType.AUTO)
- private int id;
- private String username;
- private String password;
- private String birthday;
-
-
- // 描述用户的所有订单
- @TableField(exist = false) // 表示在数据库表中不存在,不需要做映射
- private List<Order> orders;
-
- public User() {
- }
-
- public User(String username, String password, String birthday) {
- this.username = username;
- this.password = password;
- this.birthday = birthday;
- }
-
- ....省略了getter和setter方法
-
- @Override
- public String toString() {
- return "User{" +
- "id=" + id +
- ", username='" + username + '\'' +
- ", password='" + password + '\'' +
- ", birthday='" + birthday + '\'' +
- '}';
- }
- }

- @TableName("t_order")
- public class Order {
- private int id;
- @TableField("order_time")
- private String orderTime;
- private double total;
-
- @TableField(exist = false)
- private User user;
-
- public Order() {
- }
-
- public Order(String orderTime, double total, User user) {
- this.orderTime = orderTime;
- this.total = total;
- this.user = user;
- }
-
- ....省略了getter和setter方法
-
- @Override
- public String toString() {
- return "Order{" +
- "id=" + id +
- ", orderTime='" + orderTime + '\'' +
- ", total=" + total +
- ", user=" + user +
- '}';
- }
- }

- @Mapper
- public interface UserMapper extends BaseMapper<User> {
-
- // 根据id查用户
- @Select("select * from t_user where id=#{id}")
- User selectById(int id);
-
- // 查询用户及其所有的订单
- @Select("select * from t_user")
- @Results(
- {
- @Result(column = "id",property = "id"), // column:字段,property:映射到实体类的属性
- @Result(column = "username",property = "username"),
- @Result(column = "password",property = "password"),
- @Result(column = "birthday",property = "birthday"),
- @Result(column = "id",property = "orders",javaType = List.class,
- many = @Many(select = "com.org.mapper.OrderMapper.selectByUid")
- // 通过user的id去orderMapper的selectByUid查询所以该用户的订单
- )
- }
- )
- List<User> selectAllUserAndOrders();
- }

- @Mapper
- public interface OrderMapper extends BaseMapper<Order> {
-
- @Select("select * from t_order where uid=#{uid}")
- List<Order> selectByUid(int uid);
-
- // 查询所有的订单,同时查询订单用户
- @Select("select * from t_order")
- @Results({
- @Result(column = "id",property = "id"),
- @Result(column = "order_time",property = "orderTime"),
- @Result(column = "total",property = "total"),
- @Result(column = "uid",property = "user",javaType = User.class,
- one=@One(select = "com.org.mapper.UserMapper.selectById")
- // 根据order的uid到UserMapper的selectById方法中查询该订单所属的用户
- ),
- })
- List<Order> selectAllOrderAndUser();
-
- }

- @RestController
- public class UserController {
-
- @Autowired
- private UserMapper userMapper;
-
- @GetMapping("/user")
- public List<User> query() {
- // 查询用户及其所有订单
- List<User> userList = userMapper.selectAllUserAndOrders();
- return userList;
- }
-
- }
- @RestController
- public class OrderController {
-
- @Autowired
- private OrderMapper orderMapper;
-
- // 查询订单及其所属的用户
- @GetMapping("/order/findAll")
- public List findAll(){
- List<Order> orderList = orderMapper.selectAllOrderAndUser();
- return orderList;
- }
- }
- @GetMapping("/user")
- public List<User> query() {
-
- // 条件查询
- QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // 创建实例
- queryWrapper.eq("username","tom"); // 查询username为tom的用户
- List<User> userList = userMapper.selectList(queryWrapper); // 将条件作为参数传入查询方法,若无条件,则在方法传入null
- return userList;
- }
条件 | 条件实现功能 | 例子 |
---|---|---|
eq | 等于 = | 例: eq("name", "老王")--->name = '老王' |
ne | 不等于 <> | 例: ne("name", "老王")--->name <> '老王' |
gt | 大于 > | 例: gt("age", 18)--->age > 18 |
ge | 大于等于 >= | 例: ge("age", 18)--->age >= 18 |
lt | 小于 < | 例: lt("age", 18)--->age < 18 |
le | 小于等于 <= | 例: le("age", 18)--->age <= 18 |
between | BETWEEN 值1 AND 值2 | 例: between("age", 18, 30)--->age between 18 and 30 |
notBetween | NOT BETWEEN 值1 AND 值2 | 例: notBetween("age", 18, 30)--->age not between 18 and 30 |
like | LIKE '%值%' | 例: like("name", "王")--->name like '%王%' |
notLike | NOT LIKE '%值%' | 例: notLike("name", "王")--->name not like '%王%' |
likeLeft | LIKE '%值' | 例: likeLeft("name", "王")--->name like '%王' |
likeRight | LIKE '值%' | 例: likeRight("name", "王")--->name like '王%' |
isNull | 字段 IS NULL | 例: isNull("name")--->name is null |
isNotNull | 字段 IS NOT NULL | 例: isNotNull("name")--->name is not null |
in | 字段 IN (v0, v1, ...) | 例: in("age", 1, 2, 3)--->age in (1,2,3) |
notIn | 字段 NOT IN (value.get(0), value.get(1), ...) | 例: notIn("age",{1,2,3})--->age not in (1,2,3) |
- @Configuration
- public class MybatisPlusConfig {
-
- @Bean
- public MybatisPlusInterceptor paginationInterceptor(){
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); // 数据库类型
- interceptor.addInnerInterceptor(paginationInnerInterceptor);
- return interceptor;
- }
- }
- // 分页查询
- @GetMapping("/user/findByPage")
- public IPage findByPage(){
- // 设置起始值及每页条数
- Page<User> page = new Page<>(0,2);
- IPage iPage = userMapper.selectPage(page,null); // 第一个参数是page,第二个参数是查询条件
- return iPage;
- }
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
- <div id="app">
- {{ message }}
- </div>
- const vm = {
- // 指定数据源:即MVVM中的Model
- data: function(){
- return{
- message: 'Hello Vue!'
- }
- }
- }
-
- const app = Vue.createApp(hello)
- app.mount('#app) // 指定当前vue实例要控制页面的哪个区域
npm install -g @vue/cli
想了解Vue Cli项目的更多知识及操作可到Vue官网学习!!
更多语法可在Vue官网学习!!
npm i element-ui
- import Vue from 'vue'
- import App from './App.vue'
- import ElementUI from 'element-ui';
- import 'element-ui/lib/theme-chalk/index.css';
- Vue.use(ElementUI); // 全局注册
-
- Vue.config.productionTip = false
-
- new Vue({
- render: h => h(App),
- }).$mount('#app')
- <template>
- <el-table
- :data="tableData"
- style="width: 100%"
- :row-class-name="tableRowClassName">
- <el-table-column
- prop="date"
- label="日期"
- width="180">
- </el-table-column>
- <el-table-column
- prop="name"
- label="姓名"
- width="180">
- </el-table-column>
- <el-table-column
- prop="address"
- label="地址">
- </el-table-column>
- </el-table>
- </template>
-
- <script>
- export default {
- name:"Hello",
- props:[],
- data() {
- return {
- tableData: [{
- date: '2016-05-02',
- name: '王小虎',
- address: '上海市普陀区金沙江路 1518 弄',
- }, {
- date: '2016-05-04',
- name: '王小虎',
- address: '上海市普陀区金沙江路 1518 弄'
- }, {
- date: '2016-05-01',
- name: '王小虎',
- address: '上海市普陀区金沙江路 1518 弄',
- }, {
- date: '2016-05-03',
- name: '王小虎',
- address: '上海市普陀区金沙江路 1518 弄'
- }]
- }
- },
- methods: {
- tableRowClassName({row, rowIndex}) {
- if (rowIndex === 1) {
- return 'warning-row';
- } else if (rowIndex === 3) {
- return 'success-row';
- }
- return '';
- }
- }
- }
- </script>
-
- <style>
- .el-table .warning-row {
- background: oldlace;
- }
-
- .el-table .success-row {
- background: #f0f9eb;
- }
- </style>

npm install font-awesome
import 'font-awesome/css/font-awesome.min.css';
<i class="fa fa-camera-retro"></i> fa-camera-retro
npm install axios
import axios from 'axios';
- // 向给定id的用户发起请求
- axios.get('http://localhost:8080/user?id=123')
- .then(function(response){
- // 处理成功情况
- console.log(response);
- })
- .catch(function(error){
- // 处理失败情况
- console.log(error);
- })
- .then(function(){
- // 总是会执行
- });
- // 上述请求也可以按以下方式完成
-
- axios.get('http://localhost:8080/user',{
- params:{
- id:123
- }
- })
- .then(function(response){
- // 处理成功情况
- console.log(response);
- })
- .catch(function(error){
- // 处理失败情况
- console.log(error);
- })
- .then(function(){
- // 总是会执行
- });

- axios.post('http://localhost:8080/user',{
- firstName: 'Fred',
- lastName: 'Flintstone'
- })
- .then(function(response){
- console.log(response);
- })
- .catch(function(error){
- console.log(error);
- });
- // 支持async/await 用法
- async function getUser(){
- try{
- // 不需要.then就可以之间拿到response响应数据
- const response = await.axios.get('http://localhost:8080/user?id=1');
- console.log(response);
- }catch(error){
- console.error(error);
- }
- }
在实际项目开发中,几乎每个组件中都会用到axios发起的数据请求。此时会遇到如下两个问题:
每个组件中都需要导入axios
每次发送请求都需要填写完整的请求路径
可以通过全局配置的方法解决上述问题:
- // 在main.js中导入axios,然后再继续配置
- import axios from 'axios'
-
- // 配置请求根路径
- axios.defaults.baseURL = 'http://xxx'
-
- // 将axios作为全局的自定义属性,每个组件可以在内部直接访问(Vue3)
- app.config.globalProerties.$http = axios
-
- // 将axios作为全局的自定义属性(不一定$http,可以自定义),每个组件可以在内部直接访问(Vue2)
- Vue.prototype.$http = axios
- //例如:直接在其他组件中写:this.$http.get()就可以实现axios的功能
Vue项目的网络请求一般在created里面做,这样页面一创建就会发送网络请求。
- created:function(){
- axios.get("http://localhost:8888/user")
- .then((response)=>{ // 箭头函数:ES6语法,它的作用:它的作用域继承于父级(也就是Vue实例),如果用function(response),作用域就不是Vue实例
- console.log(response.data);
- this.tableData = response.data;
- console.log(this.tableData);
- })
- .catch(function(error){
- console.log(error);
- })
- },
当我们运行项目后,控制台显示报错了,这个的意思是没有明确授权同源策略,导致被CORS策略阻止。
为了保证浏览器的安全,不同源的客户端本在没有明确授权的情况下,不能读写对方资源,称为同源策略,同源策略是浏览器安全的基石。
同源策略是一种约定,它是浏览器最核心也最基本的安全功能。
所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域,此时无法读取非同源网页的Cookie,无法向非同源地址发送Ajax请求或者Axios请求。
简单请求的服务器处理
对于简单请求,CORS的策略是请求时在请求头中增加一个Origin字段。
服务器收到请求后,根据该字段判断是否允许该请求访问,如果允许,则在HTTP头信息中添加Access-Control-Allow-Origin字段。
如果没有配置跨域,是不会有Access-Control-Allow-Origin字段的。
非简单请求
对于非简单请求的跨源请求,浏览器会在真实请求发出前增加一次OPTION请求,称为预检请求(preflight request)。
预检请求将真实请求的信息,包括请求方法、自定义头字段、源信息添加到HTTP头信息字段中,询问服务器是否允许这样的操作。
例如一个GET请求:
Access-Control-Request-Method表示请求使用的HTTP方法,Access-Control-Request-Headers包含请求的自定义头字段。
服务器收到请求时,需要分别对Origin、Access-Control-Request-Method、Access-Control-Request-Headers进行验证,验证通过后,会在返回HTTP头信息中添加:
- @Configuration
- public class CorsConfig implements WebMvcConfigurer {
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**") // 允许跨域访问的路径
- .allowedOrigins("*") // 允许跨域访问的源
- .allowedMethods("POST","GET","PUT","OPTIONS","DELETE") // 允许请求的方法
- .maxAge(16800) // 预检间隔时间
- .allowedHeaders("*") // 允许头部设置
- .allowCredentials(true); // 是否发送Cookie
- }
- }
- vue-router@3在vue2中使用
- npm install vue-router@3
-
- vue-router@4在vue3中使用
- npm install vue-router@4
- <template>
- <div id="app">
- <!-- 声明路由链接 -->
- <router-link to="/teleplay">电视剧</router-link>
- <router-link to="/film">电影</router-link>
- <router-link to="/variety">综艺</router-link>
-
- <!-- 声明路由占位标签 -->
- <router-view></router-view>
- </div>
- </template>
- import VueRouter from "vue-router";
- import Vue from "vue";
- import Teleplay from '../components/Teleplay.vue'
- import Film from '../components/Film.vue'
- import Variety from '../components/Variety.vue'
-
- // 将VueRouter设置为Vue组件
- Vue.use(VueRouter)
-
- const router = new VueRouter({
- // 指定hash属性与组件的对应关系
- routes:[
- {path:'/teleplay',component:Teleplay},
- {path:'/film',component:Film},
- {path:'/variety',component:Variety}
- ]
- })
-
- export default router

- import Vue from 'vue'
- import App from './App.vue'
- import router from './router/index'
-
- Vue.config.productionTip = false
-
- new Vue({
- render: h => h(App),
- // router: router // 如果名称和属性一致可以直接写router即可
- router
- }).$mount('#app')
- // 将VueRouter设置为Vue组件
- Vue.use(VueRouter)
-
- const router = new VueRouter({
- // 指定hash属性与组件的对应关系
- routes:[
- // 当用户访问时,直接跳转访问teleplay
- {path:'/',redirect:'/teleplay'},
- {path:'/teleplay',component:Teleplay},
- {path:'/film',component:Film},
- {path:'/variety',component:Variety}
- ]
- })
-
- export default router
- <template>
- <div>
- <h1>电视剧</h1>
- <!-- 子路由链接 -->
- <router-link to="/teleplay/toplist">推荐</router-link>
- <router-link to="/teleplay/newlist">最新</router-link>
- <hr>
- <router-view></router-view>
- </div>
- </template>
- const router = new VueRouter({
- // 指定hash属性与组件的对应关系
- routes:[
- // 当用户访问时,直接跳转访问teleplay
- {path:'/',redirect:'/teleplay'},
- {
- path:'/teleplay',
- component:Teleplay,
- // 通过children属性,嵌套声明子路由
- children:[
- {path:'toplist',component: Toplist},
- {path:'newlist',component: Newlist}
- ]
- },
- {path:'/film',component:Film},
- {path:'/variety',component:Variety},
- ]
- })
-
- export default router

- {
- path:'/film',
- component:Film,
- children:[
- {path:':id',component:Filmdetail},
- ]
- },
- {
- path:'/film',
- component:Film,
- children:[
- {path:':id',component:Filmdetail,props:true},
- ]
- },
- <template>
- <div>
- <h1>电影详情页</h1>
- <!-- 获取动态的id值 -->
- <p>电影{{id}}</p>
- </div>
- </template>
-
- <script>
- export default{
- // 组件名称
- name:'Filmdetail',
- props:["id"] // 定义属性名称
- }
- </script>
这样就可以根据自己自定义的属性来获取传过来的参数。
声明式 | 编程式 |
---|---|
<router-link to="..."> | router.push(...) |
- <template>
- <div>
- <h1>电影</h1>
- <router-link to="/film/1">电影1</router-link>
- <router-link to="/film/2">电影2</router-link>
- <router-link to="/film/3">电影3</router-link>
- <!-- 路由占位标签 -->
- <router-view></router-view>
-
- <button v-on:click="gotoFilmdetail(3)">跳转到电影3</button>
-
- </div>
- </template>
-
- <script>
- export default{
- methods:{
- gotoFilmdetail:function(id){
- this.$router.push('/filmdetail/'+id); // 跳转到特定的url(必须有声明的url)
- }
- }
- }
- </script>

- router.beforeEach((to,from,next)=>{
- if(to.path === '/main' && !isAuthenticated){
- next('/login');
- }else{
- next();
- }
- });
- 这是vue2版本
- npm install vuex@3
-
- 这是vue3版本
- npm install vuex@4
- import Vue from "vue";
- import Vuex from "vuex";
-
- Vue.use(Vuex);
-
- const store = new Vuex.Store({
- state:{
- count:0,
- },
- mutations:{
- increment(state){
- state.count++;
- }
- }
- })
-
- export default store;

- // 导入store
- import store from './store/index'
-
- new Vue({
- render: h => h(App),
- store:store
- }).$mount('#app')
- <template>
- <div>
- <h1>TestStore</h1>
- <h2>{{this.$store.state.count}}</h2>
- <button @click="add">+1</button>
- </div>
- </template>
-
- <script>
- export default{
- name:'TestStore',
- methods:{
- add(){
- this.$store.commit("increment");
- }
- }
- }
- </script>

- const store = new Vuex.Store({
- state:{
- count:0
- },
- mutations:{
- increment(state){
- state.count++;
- }
- }
- })
- <template>
- <div>
- <h1>TestStore</h1>
- <h2>{{this.$store.state.count}}</h2>
- </div>
- </template>
- import {mapState} from 'vuex'
-
- export default{
- name: 'TestStore',
- computed: mapState({
- // 箭头函数可使代码更加简练
- count: state => state.count,
-
- // 传字符串参数 'count' 等同于 'state => state.count'
- countAlias: 'count',
-
- // 为了能够使用'this'获取局部状态,必须使用常规函数
- countPlusLocalState(state){
- return state.count + this.localCount
- }
- })
- }

- computed: mapState([
- // 映射 this.count 为 store.state.count
- 'count'
- ])
- computed:{
- // 这是自定义的一个计算属性
- localComputed(){....},
-
- // 使用对象展开运算符("...")将此对象混入到外部对象中
- ...mapState({
- // ...
- })
- }
- const store = new Vuex.Store({
- state:{
- todos:[
- {id:1,text:"吃饭",done:true},
- {id:2,text:"睡觉",done:false}
- ]
- },
- getters:{
- doneTodos: (state) => {
- return state.todos.filter(todo => todo.done===false);
- }
- }
- })
- <script>
- import { mapGetters } from 'vuex';
- export default{
- name:'TestStore',
- computed: {
-
- // 使用对象展开运算符将getter混入computed对象中
- ...mapGetters([
- 'doneTodos'
- ])
- }
- }
- </script>
- <template>
- <div>
- <ul>
- <li v-for="todo in doneTodos" :key="todo.id">{{todo.text}}</li>
- </ul>
- </div>
- </template>
- const store = new Vuex.Store({
- state:{
- count:0
- },
- mutations:{
- increment(state){
- state.count++;
- }
- }
- })
- methods: {
- increment(){
- this.$store.commit('increment')
- console.log(this.$store.state.count)
- }
- }
- methods:{
- ...mapMutations([
- 'increment', // 将'this.increment()'映射为'this.$store.commit('increment')'
-
- // 'mapMutations'也支持载荷:(可以传入额外的参数,即为载荷)
- 'incrementBy' // 将'this.incrementBy(amount)'映射为'this.$store.commit('incrementBy',amount)'
- ]),
- }
- const store = createStore({
- state: {
- count: 0;
- },
- mutations: {
- increment(state){
- state.count ++;
- }
- },
- actions: {
- increment(context){
- context.commit('increment');
- }
- }
- })
- methods:{
-
- ...mapActions([
- 'increment', // 将'this.increment()' 映射为 'this.$store.dispatch('increment')'
-
-
- // 'mapActions' 也支持载荷:
- 'incrementBy' // 将 'this.incrementBy(amount)' 映射为 'this.$store.dispatch('incrementBy',amount)'
- ]),
-
- ...mapActions({
- add: 'increment' // 将'this.add()' 映射为 'this.$store.dispatch('increment')'
- })
- }
- const moduleA = {
- state: ()=>({...}),
- mutations: {...},
- actions:{...},
- getters: {...}
- }
-
- const moduleB = {
- state: ()=>({...}),
- mutations: {...},
- actions:{...}
- }
-
- const store = createStore({
- modules: {
- a: moduleA,
- b: moduleB
- }
- })
-
- store.state.a // ——>moduleA的状态
- store.state.b // ——>moduleB的状态

npm install mockjs
- // 引入mock.js
- import Mock from 'mockjs'
-
- // 设置延迟时间
- // Mock.setup({
- // timeout: 400
- // })
-
- // 使用mock.js模拟数据
- Mock.mock('/product/search',{
- "ret": 0,
- "data":
- {
- "mtime": "@datatime", // 随机生成日期时间
- "score|1-800": 800, // 随机生成1-800的数字
- "rank|1-100": 100, // 随机生成1-100的数字
- "stars|1-5": 5, // 随机生成1-5的数字
- "nickname": "@cname", // 随机生成中文名字
- "img": "@image('200x100','#ffcc33','#FFF','png','Fast Mock')"
- // 尺寸 背景颜色 文字颜色 图片格式 图片文字
- }
-
- })

import './mock/index'
- import axios from 'axios'
-
- export default{
- mounted:function(){
- axios.get("/product/search")
- .then(res=>{
- console.log(res)
- })
- }
- }
- // 延时400ms请求到数据
- Mock.setup({
- timeout: 400
- })
-
- // 延时200-600ms请求到数据
- Mock.setup({
- timeout: '200-600'
- })
- // 属性名 name
- // 生成规则 rule
- // 属性值 value
- 'name|rule': value
互联网服务离不开用户认证。一般是一下流程:
Token是在服务端产生的一串字符串,是客户端访问资源接口(API)时所需要的资源凭证,流程如下:
- <!--JWT-->
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
- public class JwtUtil {
-
- // 7天过期
- private static long expire = 604800;
- // 32位秘钥
- private static String secret = "abcdfghiabcdfghiabcdfghiabcdfghi";
-
- // 生成token
- public static String generateToken(String username){
- Date now = new Date();
- Date expiration = new Date(now.getTime() + 1000 * expire);
- return Jwts.builder()
- .setHeaderParam("type","JWT") // 设置Header
- .setSubject(username) // 设置负载
- .setIssuedAt(now) // 设置生效时间
- .setExpiration(expiration) // 设置过期时间
- .signWith(SignatureAlgorithm.HS512,secret) // 指定签名算法
- .compact();
- }
-
- // 解析token
- public static Claims getClaimsByToken(String token){
- return Jwts.parser()
- .setSigningKey(secret) // 传密钥,查看是否有篡改
- .parseClaimsJws(token) // token是否正确
- .getBody();
- }
- }

- @PostMapping("/login")
- public String login(@RequestBody User user){ // 用@RequestBody接收,前台就需要发送的是json格式
- String token = JwtUtil.generateToken(user.getUsername());
- return token;
- }
- @GetMapping("/info")
- public String info(String token){
- String username = JwtUtil.getClaimsByToken(token).getSubject(); // 解析token获取用户名
- return username;
- }
- # 查找 是否安装了mariadb
- rpm -qa|grep mariadb
- # mariadb-libs-5.5.52-1.el7.x86_64
- # 卸载(版本根据自己系统自带的自行更改)
- rpm -e mariadb-libs-5.5.52-1.el7.x86_64 --nodeps
解压MySQL
- # 创建mysql安装包存放点
- mkdir /usr/server/mysql
- # 解压
- tar xvf mysql-5.7.34-1.el7.x86_64.rpm-bundle.tar
执行安装
- # 切换到安装目录
- cd /usr/server/mysql/
- yum -y install libaio
- yum -y install libncurses*
- yum -y install perl perl-devel
- # 安装
- rpm -ivh mysql-community-common-5.7.34-1.el7.x86_64.rpm
- rpm -ivh mysql-community-libs-5.7.34-1.el7.x86_64.rpm
- rpm -ivh mysql-community-client-5.7.34-1.el7.x86_64.rpm
- rpm -ivh mysql-community-server-5.7.34-1.el7.x86_64.rpm
启动MySQL
- #启动mysql
- systemctl start mysqld.service
- #查看生成的临时root密码
- cat /var/log/mysqld.log | grep password
修改初始的随机密码
- # 登录mysql
- mysql -u root -p
- Enter password: #输入在日志中生成的临时密码
- # 更新root密码 设置为root(密码自行定义,后面远程连接需要用到)
- set global validate_password_policy=0;
- set global validate_password_length=1;
- set password=password('root');
授予远程连接权限
- # 让数据库支持远程连接
- grant all privileges on *.* to 'root' @'%' identified by 'root';
- # 刷新
- flush privileges;
控制命令
- #mysql的启动和关闭 状态查看
- systemctl stop mysqld
- systemctl status mysqld
- systemctl start mysqld
- #建议设置为开机自启动服务
- systemctl enable mysqld
- #查看是否已经设置自启动成功
- systemctl list-unit-files | grep mysqld
关闭防火墙
- firewall-cmd --state #查看防火墙状态
- systemctl stop firewalld.service #停止firewall
- systemctl disable firewalld.service #禁止firewall开机启动
- yum install epel-release
- yum update
- yum -y install nginx
- systemctl start nginx #开启nginx服务
- systemctl stop nginx #停止nginx服务
- systemctl restart nginx #重启nginx服务
tar -zvxf jdk-8u131-linux-x64.tar.gz
- vi /etc/profile
- # 文件末尾增加
- export JAVA_HOME=/usr/server/jdk1.8.0_351
- export PATH=${JAVA_HOME}/bin:$PATH
source /etc/profile
java -version
npm run build
- server {
- listen 80;
- server_name locahost;
- location / {
- root /usr/app/dist;
- index index.html;
- }
- }
nginx -s reload
- # 表示让java程序在后台运行,然后生成运行日志,方便查看项目是否报错。
- nohup java -jar shop-0.0.1-SNAPSHOT.jar > logName.log 2>&1 &
项目正常运行了,说明部署成功了,这样项目所有人就可以访问了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。