后端
一.项目初始化
1.创建springboot项目
2.添加pom依赖
-
使用了Spring Boot提供的父级依赖来管理项目的依赖版本和配置。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.8</version> <relativePath/> <!-- lookup parent from repository --> </parent>
relativePath
被设置为一个空值,表示Maven会从仓库中查找父级依赖的信息。
-
添加依赖
<!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mysql --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.2</version> </dependency> <!-- freemarker --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
[spring-boot-starter-web] 导入这个依赖才能使yml文件修改tomcat端口生效
-
启动器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
5.设置application.yml
-
端口和数据库
server: port: 8259 spring: datasource: username: root password: 123456 url: jdbc:mysql:///mdb redis: port: 6379 host: localhost
[url: jdbc:mysql:///mdb] 因为是本地数据库所以省略了localhost 实际是 jdbc:mysql://localhost/mdb mdb是数据库名字
[server.port: 8259] 如果已经导入依赖包修改端口还没有生效的话,检查一下缩进
二、MyBatis-Plus生成代码
1.新建代码生成器CodeGenerator
-
新增类(可以放到test模块下)
-
类中新增main方法用来启动代码生成器
String url = "jdbc:mysql://localhost:3306/dirary"; String username = "root"; String password = "ljp211200"; String moduleName = "sys"; String mapperLocation ="E:\\test\\Diary_sys\\src\\main\\resources\\mapper\\" + moduleName; String tables = "d_user,d_role,d_menu,d_user_role,d_role_menu"; FastAutoGenerator.create(url, username, password) .globalConfig(builder -> { builder.author("lijunpeng") // 设置作者 //.enableSwagger() // 开启 swagger 模式 //.fileOverride() // 覆盖已生成文件 .outputDir("E:\\test\\Diary_sys\\src\\main\\java"); // 指定输出目录 }) //旧版fileOverride在3.5.2版本已经被移除不可用,可以使用3.5.1版本解决这个问题,或者用以下配置 // .strategyConfig(builder -> { // builder.entityBuilder() // .enableLombok() // .fileOverride() // .controllerBuilder() // .enableRestStyle() // .fileOverride() // .mapperBuilder() // .enableBaseResultMap() // .enableBaseColumnList() // .fileOverride(); // }) .packageConfig(builder -> { builder.parent("org.lijunpeng") // 设置父包名 .moduleName(moduleName) // 设置父包模块名 .pathInfo(Collections.singletonMap(OutputFile.xml, mapperLocation)); // 设置mapperXml生成路径 }) .strategyConfig(builder -> { builder.addInclude(tables) // 设置需要生成的表名 .addTablePrefix("d_"); // 设置过滤表前缀 }) .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板 .execute();
[String username ] 前面的变量是手动配置的,为了方便以后配置参数设置成变量
[outputDir(E:\\test\\Diary_sys\\src\\main\\java)] 指定生成的java代码存放的位置
[org.lijunpeng] 父包名为存放项目java代码的包
[moduleName] 父包模块名,生成的java代码所在的模块,系统每新增一个板块功能就修改一下这个模块名生成不同的模块
[mapperLocation] 指定mapperml代码所在位置
-
注意事项:生成代码需要先创建对应的数据库,并提前创建表
2.添加mapper接口注解
-
代码生成之后,mapper接口是没有注解的。需要再启动类上增加一个mapper扫描
@MapperScan("org.lijunpeng.*.mapper") public class DiaryApplication { public static void main(String[] args) { SpringApplication.run(DiaryApplication.class, args); } }
-
中间加 * 是因为模块名有很多
3.添加测试类,测试Mapper
-
新建测试类
@SpringBootTest public class DiaryApplicationTests { @Resource private UserMapper userMapper; @Test void testMapper(){ List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } }
-
注入mapper
@Resource private UserMapper userMapper;
-
测试
List<User> users = userMapper.selectList(null); users.forEach(System.out::println);
4.Contrallor测试
-
装配Service对象
-
更改请求路径
@Controller @RequestMapping("/user") public class UserController { @Autowired private IUserService userService; @GetMapping("/all") public List<User> getAllUser(){ List<User> list = userService.list(); return list; } }
-
运行启动类,在浏览器测试
-
如果报错:404 意味着ip和端口正确但是路径错误
-
如果都正确,可能是注解错误,
@Controllor注解返回的是视图结果,前后端对接需要的是Josn结果
-
将@Controllor改成@RestControllor,
@RestControllor会将结果以Josn形式返回
三、公共响应类
1.创建Rusult类
-
不同的方法返回的数据格式会不同,为了统一前后端传递数据的格式需要创建一个这样的类
-
org.lijunpeng下新增common.vo.Result(vo是value object值对象)
@Data @NoArgsConstructor @AllArgsConstructor public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> success(){ return new Result<>(20000, "success", null); } public static <T> Result<T> success(T data){ return new Result<>(20000, "success", data); } public static <T> Result<T> success(T data, String message){ return new Result<>(20000, message, data); } public static <T> Result<T> success(String message){ return new Result<>(20000, message, null); } public static <T> Result<T> fail(){ return new Result<>(20001, "message", null); } public static <T> Result<T> fail(Integer code){ return new Result<>(code, "message", null); } public static <T> Result<T> fail(String message) { return new Result<>(20001, message, null); } public static <T> Result<T> fail(Integer code, String message){ return new Result<>(code, message, null); } }
-
测试
@GetMapping("/all") public Result<List<User>> getAllUser(){ List<User> list = userService.list(); return Result.success(list); }
四、接口
1.登录
接口属性 | 值 |
---|---|
url | /user/login |
method | post |
请求参数 | username password |
返回参数
{ "code": 20000, "message": "success" "data": { "token": "fdsaf23-fad3f1-sfa3df1a23f13d" } }
-
实现登录接口
-
UserContrallor控制器
-
@Autowired private IUserService userService; @PostMapping("/login") public Result<Map<String,Object>> login(User user){ Map<String, Object> data = userService.login(user); if (data != null){ return Result.success(data); } return Result.fail(20002,"用户名或密码错误"); }
设置接口调用路径,创建接口对应的方法
-
IUserService接口
-
Map<String, Object> login(User user);
-
UserServiceImpl实现接口
-
配置Redis
-
@Autowired private RedisTemplate redisTemplate;
-
实现login接口
-
@Override public Map<String, Object> login(User user) { //<User> 查询结果为User类型 LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getUsername,user.getUsername()); wrapper.eq(User::getPassword,user.getPassword()); User loginuser = this.baseMapper.selectOne(wrapper); //结果不为空,返回用户信息并将用户信息存入redis,生成token if (loginuser != null){ //生成token,暂时用UUID,终极方案是jwt String key = "user:" + UUID.randomUUID(); //存入redis loginuser.setPassword(null); redisTemplate.opsForValue().set(key,loginuser,30, TimeUnit.MINUTES); //返回数据 Map<String, Object> data = new HashMap<>(); data.put("token",key); return data; } return null; }
-
配置Redis
-
@Resource private RedisConnectionFactory factory; @Bean public RedisTemplate redisTemplate(){ RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); redisTemplate.setKeySerializer(new StringRedisSerializer()); Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); redisTemplate.setValueSerializer(serializer); //序列化 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); om.setTimeZone(TimeZone.getDefault()); om.configure(MapperFeature.USE_ANNOTATIONS, false); om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); om.setSerializationInclusion(JsonInclude.Include.NON_NULL); serializer.setObjectMapper(om); return redisTemplate; }
-
Mapper Contrallor Service Impl 关系
前端调用Contrallor
Contrallor调用Impl方法
Impl方法是Service接口的实现
Impl查询数据,通过Mapper连接数据库
-
get请求和post请求
get请求不会修改数据,post请求会修改数据。在这个登录接口中,post更改的是Redis数据
2.获取用户信息
-
配置fastjson反序列化依赖
<!-- fastjson --> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.7</version> </dependency>
-
实现接口
@Override public Map<String, Object> getUserInfo(String token) { //根据token获取用户信息,Redis Object obj = redisTemplate.opsForValue().get(token); //反序列化对象obj,先转换成json字符串再反序列化成User对象 if (obj != null){ User loginUser = JSON.parseObject(JSON.toJSONString(obj),User.class); Map<String, Object> data = new HashMap<>(); data.put("username",loginUser.getUsername()); data.put("name",loginUser.getName()); List<String> roleList = this.baseMapper.getRoleNameByUserName(loginUser.getUsername()); data.put("roles", roleList); return data; } return null; }
3.注销
-
登录之后所有前端操作的参数都在请求头Header里