课程内容
-
前端:vue elementui
-
后端:springboot mybatisplus
-
公共云部署
------boot--------
热部署
不用devtools,交给jrebel工具
+++
@RequestMapping
参数
- value 路径 method 方法
- consumes 请求媒体类型 如 application/json
- produces 响应媒体类型
- params, headers 请求参数和请求头值
// localhost:8080/user?username=123&pwd=456,注意传递的是pwd,且非必须
@GetMapping(value = "/user")
public String Student(String username,@RequestParam(value = "pwd",required = false) String password) {
return username + password;
}
就是json数据
// http://localhost:8080/user2
@PostMapping(value = "/user2")
public String user2(@RequestBody User user) {
System.out.println(user);
return "post请求";
}
+++
配置静态资源路径
mvc:
static-path-pattern: /images/** # 地址栏路径
web:
resources:
static-locations: classpath:/static/ # 本地路径
配置文件上传大小
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
上传controller代码
@RestController
public class FileUploadController {
@PostMapping("/upload")
public String upload(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException {
String path = request.getServletContext().getRealPath("/upload/");
saveFile(photo, path);
return "上传成功";
}
public void saveFile(MultipartFile photo, String path) throws IOException {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(path + photo.getOriginalFilename());
photo.transferTo(file);
}
}
+++
配一下本地静态资源路径,可以在浏览器访问上传的图片:
web:
resources:
static-locations: /upload/
+++
拦截器
使用:登录 监控性能 通用行为(改编码格式)
配置拦截器指定拦截路径 /user/**
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");
}
}
拦截器 true通过 false不通过
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截");
return false;
}
}
+++
RESTful
GET获取资源 POST新建资源 PUT更新资源 DELETE删除资源
@GetMapping @PostMapping @PutMapping @DeleteMapping
资源表现为 JSON或HTML
状态码
2xx 成功
3xx 重定向
4xx 客户端错误
5xx 服务器错误
+++
方法 | 地址 |
---|---|
GET | /user/{id} |
POST | /user |
PUT | /user |
DELETE | /user/{id} |
@GetMapping("/user/{id}")
public String getUserById(@PathVariable int 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) {
return "根据ID删除用户";
}
Swagger 2
功能:接口的调试和文档
导入依赖
配置
<!-- swagger依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
配置类
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com"))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("演示项目API")
.description("演示项目")
.version("1.0")
.build();
}
}
MybatisPlus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 数据连接池 druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置数据库
boot中用xml和注解混合开发mybatis
xml方式:
yml配置
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.sbdemo1.mapper
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
datasource:
url: jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
@Mapper
public interface TestMapper {
List<Student> getAllStudent();
}
通过小鸟直接定位到xml,注意xml配置文件位置是yml定义的,两个小鸟同名
<?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.example.sbdemo1.mapper.TestMapper">
<select id="getAllStudent" resultType="com.example.sbdemo1.entity.Student">
select * from student
</select>
</mapper>
MybatisPlus 对多表无能为力,但是可以
条件查询
使用官方提供的条件包装类QueryWrapper
@Test
void MainTest() {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "甘雨"); // 查询和甘雨同名的那一条
mapper.selectList(queryWrapper).forEach(System.out::println);
}
分页查询
配置分页拦截器
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
@Test
void MainTest() {
Page<Student> studentPage = new Page<>(0, 2);
IPage iPage = mapper.selectPage(studentPage, null);
}
只查了前两个数据
==> Preparing: SELECT sid,name,sex FROM student LIMIT ?
==> Parameters: 2(Long)
<== Columns: sid, name, sex
<== Row: 3, 丽莎, 男
<== Row: 7, 六月七, 女
<== Total: 2
Closing non transactio
+++
--------Vue--------
MVVM > MVC
基本模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基本用法</title>
<script src="../vue.global.js"></script>
</head>
<body>
<!--声明被vue控制的DOM区域-->
<div id="app">{{miku}}</div>
<!--创建vue实例对象-->
<script>
Vue.createApp({
data() {
return {miku: "初音"};
}
}).mount("#app")
</script>
</body>
</html>
组件化开发
NPM :NodeJS包管理分发工具,类似maven
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kwBbC0kb-1685364834479)(null)]
vuecli脚手架搭建项目
npm install -g @vue/cli
vue create hello
Manually select features
空格去掉 Linter/Formatter
选择3
In package.json
N
直接IDEA创建工程 ~
+++
组件化开发:把代码抽象成一组物件重复使用
组件(*.vue) { template [模板(html或其他组件{组件可以互相嵌套})],script [js代码],style [样式] }
+++
组件传值:data,父组件通过prop,兄弟之间通过Vuex
+++
第三方组件
+++
element ui
导入组件cv使用即可
+++
font awesome
导入图标
+++
Axios
前端和服务器传递数据
使用XMLHttpRequests发送网络请求,自动转换JSON
+++
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IkLGXdlj-1685364834544)(null)]
+++
+++
不常用
+++
配置文档
+++
后端向前端传递数据跨域错误
后端controller
@RestController
public class StudentController {
@Resource
TestMapper mapper;
// http://localhost:8088/user/find
@GetMapping(value = "/user/find")
public List<Student> find() {
return mapper.selectList(null);
}
}
前端axios
created() { //生命周期函数
axios.get("http://localhost:8088/user/find").then(function (response) {
console.log(response)
})
},
mounted() {
console.log("挂载App组件")
},
components: {
AnimeComponent,
HelloComponent,
}
跨域保证安全,浏览器遵循同源
策略,同源指的是协议,主机,端口号相同
http://localhost:8080 <- 这三部分必须相同
+++
解决
在对应控制器加注解即可
@RestController
@CrossOrigin <-- Here
public class StudentController {
+++
HelloComponent.vue
main.js
+++
vue router 前端路由
vue单页面基于路由和组件
+++
VueX 状态管理
管理分散的数据
+++
mockjs模拟后端生成随机数据
+++
vue-element-admin
后台前端解决方案,基于vue和elementui实现
+++
跨域认证
session 认证过程
拓展性不好,session的跨域问题,解决方案:
-
把session存到redis中
数据持久化
-
所有数据存在客户端,
Token认证
+++
token [令牌] 认证
登录后,服务器产生token字符串给客户端,作为客户端访问资源的凭证
+++
jwt (token的实现)
全称JSON Web Token,发送的token字符串是 JSON对象,
+++
实现
导入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
生成token
private static Long expire = 604800L;
private static String secret = "cereshuzhitingnizhenbangcereshuzhitingnizhenbang";
public static String generateToken(String username) {
Date now = new Date();
Date expiration = new Date(now.getTime() + 1000 * expire);
return Jwts.builder()
.setHeaderParam("type", "JWT")
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public static Claims getClaimsByToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
+++
封装工具方法返回信息
package com.example.sbdemo1.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.HashMap;
import java.util.Map;
/**
* --- Hello, World ---
*
* @author FuGuangjian
* @version 2023/5/1 16:45
* @desc 统一返回结果的类
*/
@Data
@Accessors(chain = true)
public class R {
private Boolean success;
private Integer code;
private String message;
private Map<String, Object> data = new HashMap<>();
private R() {
}
public static R ok() {
return new R().setSuccess(true).setCode(RCode.SUCCESS).setMessage("成功");
}
public static R error() {
return new R().setSuccess(false).setCode(RCode.ERROR).setMessage("失败");
}
public R success(Boolean success) {
this.setSuccess(success);
return this;
}
public R message(String message) {
this.setMessage(message);
return this;
}
public R code(Integer code) {
this.setCode(code);
return this;
}
public R data(String key, Object value) {
this.data.put(key,value);
return this;
}
public R data(Map <String, Object> map) {
this.setData(map);
return this;
}
}
+++
public interface RCode {
public static Integer SUCCESS = 20000; //成功
public static Integer ERROR = 200001; //失败
}
+++
npm 镜像
npm install --registry=https://registry.npmmirror.com
is;
}
public R message(String message) {
this.setMessage(message);
return this;
}
public R code(Integer code) {
this.setCode(code);
return this;
}
public R data(String key, Object value) {
this.data.put(key,value);
return this;
}
public R data(Map <String, Object> map) {
this.setData(map);
return this;
}
}
+++
```java
public interface RCode {
public static Integer SUCCESS = 20000; //成功
public static Integer ERROR = 200001; //失败
}
+++
npm 镜像
npm install --registry=https://registry.npmmirror.com