前后端分离:后端部署

后端

一.项目初始化

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
methodpost
请求参数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里

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值