实训Day03

学习目标

1.controller的完善

利用@RequestBody

​ 使用时,方法的请求方式必须是post,将参数设置为json格式

​ 在发送时,采用Context-Type为application/json方式传递参数

​ 后端接收到json字符串后,再利用jackson(默认的springboot整合的json解析工具)解析json字符串

​ 核心方法ObjectMapper

对返回结果的增强–R类

2.java操作数据(DAO 持久层)

​ jdbc

​ MyBatis

​ MyBatis-Plus

今日所学

更新项目目录

在这里插入图片描述

1.swagger的使用加强

@Api 对控制器本身进行描述 声明在控制器类中

@Api(value="UserController",tags="用户操作接口")
public void class UserController{}

@ApiOperation 对参数进行描述

@ApiOperation(value = "register",tags = "用户注册方法",notes = "用户注册注意事项")
public User register(UserRegisterDto dto){}

@ApiParam 声明在参数中

public User getByid(@ApiParam Integer id){}

@ApiImplicitParam 声明在方法中

@ApiImplicitParams 声明在方法中,包含多个@ApiImplicitParam

@ApiImplicitParams({
            @ApiImplicitParam(value = "id",name = "用户id")
    })
public User getByid(Integer id){}

@ApiModel 对实体类增强描述

@ApiModelProperties

@ApiModel(value = "UserDto",description = "用户对象Dto传输数据")
public class UserDto implements Serializable {
    @ApiModelProperty(value = "phone",name = "用户手机号")
    private String phone;
    @ApiModelProperty(value = "pwd",name = "用户密码")
    private String pwd;
}

2.接口设计中的约定

​ 1.所有方法的返回类型都是R

​ 2.简单的查询方法中(getByid)使用get请求方式

​ 3.复杂的参数情况用dto对象封装,如果有敏感字段就应该使用json(请求类型为post

​ 4.查询一般用GET请求方式,而增删改操作一般用POST请求方式

​ 5.复杂的查询用dto封装查询条件(查询特征/分页特征)要用POST请求方式

​ 6.restful风格的开发方式

get 查询		http://localhost:8080/user/1
post 添加		http://localhost:8080/user
put 修改		http://localhost:8080/user
delete 删除	http://localhost:8080/user/1
//以编号为1的用户做CRUD操作

//查询
GET  http://localhost:8080/user/1

@GetMapping("/{id}")
public void select(@PathVariable("id") Integer id){}

//删除
DELETE http://localhost:8080/user/1

@DeleteMapping("/{id}")
public Boolean delete(@PathVariable("id") Integer id){}

//添加
POST http://localhost:8080/user

@PostMapping("")
public Boolean insert(@RequestBody UserDto dto){}

//修改
POST http://localhost:8080/user

@PutMapping("")
public Boolean update(@RequestBody UserDto dto){}

3.Controller的增强

异常处理

初步方案

利用try-catch进行异常处理,相对于throws,好处在于try-catch可以在方法内部局部处理异常,而不是将异常传递给调用者。这样可以更灵活地处理异常,根据具体情况选择如何处理异常,而不是强制调用者处理。

但是当不知道异常可能存在哪个语句中,就需要将所有语句都放在try中,这样就造成了代码的复杂冗余,也使代码可读性降低。

PostMapping("/login")
public R login(@RequestBody UserDto dto) {
        try{
            int i = 1/0;
            UserVo vo = null;
            if("133".equals(dto.getPhone()) && "123456".equals(dto.getPwd())){
                // 登录成功
                vo = new UserVo();
                vo.setId(1);
                vo.setName("张三丰");
                vo.setPhone("13312345678");
                vo.setPwd("123456");
                // 使用UUID来快速生成一个给前端颁发的token串
                String token = UUID.randomUUID().toString().replaceAll("-","");
                vo.setToken(token);
            }
            return vo!=null? R.success(vo) : R.error();
        }catch (Exception e){
            return R.error("系统开小差了, 请稍后再试");
        }
}
优化处理
使用封装方式

AOP(面向切面编程)(底层原理:动态代理)

由于我们知道每次都需要用到try-catch,那么我们有理由猜想可以将try-catch代码块进行封装,形成一个所谓的模板

@PostMapping("/login")
public R ****(@RequestBody UserDto dto) {
        try{
        	...
        }catch (Exception e){
        	return R.error("系统开小差了, 请稍后再试");
        }
}
采用全局异常处理器

1.@RestControllerAdvice:聚合注解,结合了@ControllerAdvice@ResponseBody,用于定义全局异常处理类,并将处理结果直接返回给客户端。

2.@ExceptionHandler(Throwable.class):异常处理方法,用于捕获所有Throwable类型的异常,即所有可能抛出的异常都会被这个方法捕获。

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Throwable.class)
    public R handler(){
        return R.error("系统开小差了, 请稍后再试");
    }
}

4.实现在控制器中进行功能处理

创建普通类封装方法

一个接口的设计成功/失败都具有一个统一的返回类型:R(自己命名)

R中包括的信息:code(状态码)/msg(后端返回给前端的信息)/data(数据)…

@Data
public class R implements Serializable {
    private Integer code;
    private String msg;
    private Object data;

    public static R success(){
        R r = new R();
        r.setCode(200);
        r.setMsg("success");
        return r;
    }

    public static R success(Object data){
        R r = new R();
        r.setData(data);
        return r;
    }

    public static R failed(){
        R r = new R();
        r.setCode(0);
        r.setMsg("failed");
        return r;
    }

    public static R failed(String msg){
        R r = new R();
        r.setCode(0);
        r.setMsg(msg);
        return r;
    }
}

自定义异常类

public class BizException extends Exception{
    public BizException(ErrorCode errorCode){
        super(errorCode.getMsg());
    }
}

全局异常处理控制器

@RestControllerAdvice
public class GlobalExceptionHander {
    @ExceptionHandler(BizException.class)
    public R handerBizException(BizException e){
        return R.failed(e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public R handerThoowable(){
        return R.failed("服务器开小差,请稍后再试...");
    }
}

创建枚举类

注意:枚举常量的名字需要全大写

public enum ErrorCode {
    ERROR_LOGIN(501,"登陆失败,用户名或密码错误"),
    ERROR_USER(502,"查询用户不存在"),
    ERROR_REGISTER(503,"该手机号已经被注册了")
    ;
    private Integer code;
    private String msg;

    ErrorCode(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

查找方法

简单利用id进行查找用户

如果id值大于5那么返回用户不存在的信息(因为还没涉及到数据库,所以简单练习一下全局异常处理器,下面也是同理)

@GetMapping("/getByid")
public User getByid(Integer id) throws BizExceptio
    User user = new User();
    user.setId(id);
    user.setName("张三丰");
    user.setPhone("123");
    user.setPwd("12345
    if (id > 5){
        throw new BizException(ErrorCode.ERROR_USER);
  
    return user;

查找检测

在这里插入图片描述

登陆方法

通过给定的电话和密码去判断用户登陆信息是否正确

@PostMapping("/login")
@ApiOperation(value = "用户登陆方法",notes ="{\n" +
        "  \"phone\": \"123\",\n" +
        "  \"pwd\": \"12345\"\n" +
        "}")
public R login(@RequestBody UserDto dto) throws BizException{
    UserVo userVo = null
    if ("123".equals(dto.getPhone()) && "12345".equals(dto.getPwd())){
        userVo = new UserVo;
        userVo.setId(1);
        userVo.setName("张三丰");
        userVo.setPhone("123");
        userVo.setPwd("12345");
        String token = UUID.randomUUID().toString().replaceAll("-","");
        userVo.setToken(token);
  
    if (userVo == null){
        throw new BizException(ErrorCode.ERROR_LOGIN);
  
    return R.success(userVo);
}

登陆检测

在这里插入图片描述
在这里插入图片描述

注册方法

简单实现如果输入框内容不为空即可注册成功

判断如果注册电话是133,那么返回一个电话已经被注册的信息

@PostMapping("/register")
    @ApiOperation(value = "register",tags = "用户注册方法",notes = "{\n" +
            "  \"name\": \"zhangsan\",\n" +
            "  \"phone\": \"123\",\n" +
            "  \"pwd\": \"12345\"\n" +
            "}")
    public R register(@RequestBody UserRegisterDto dto) throws BizException {

        User user = null;
        if (!"".equals(dto.getName()) && !"".equals(dto.getPhone()) && !"".equals(dto.getPwd())){
            user = new User();

            //利用Spring框架的工具类进行数据复制
            BeanUtils.copyProperties(dto,user);
        }

        if ("133".equals(user.getPhone())){
            throw new BizException(ErrorCode.ERROR_REGISTER);
        }

        return R.success(user);
    }

注册检测

在这里插入图片描述
在这里插入图片描述

5.动态代理

作用

在java程序编译或运行期间动态生成一个对象

分类

jdk动态代理

cglib动态代理

package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserMapperProxy {
    // 通过动态代理生成UserMapper的实例
    public void test(){
        // Proxy 代理类
        // newProxyInstance 创建代理对象的方法
        // 类加载器的实例
        ClassLoader classLoader = this.getClass().getClassLoader();
        // interfaces
        Class[] interfaces = {UserMapper.class};
        UserMapper userMapper = (UserMapper) 				Proxy.newProxyInstance(classLoader,
                interfaces, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws
                            Throwable {
                        return method.invoke(proxy,args);
                    }
                });
        userMapper.getById(1);
    }
}
  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的C语言万年历的实训报告,供您参考: 一、实训目的 本次实训的主要目的是通过编写一个简单的C语言万年历程序,巩固C语言基本语法和编程思想,提高编程能力和解决问题的能力。 二、实训要求 1、能够使用C语言基本语法和控制语句编写程序。 2、能够使用数组来存储和操作数据。 3、能够使用函数来实现模块化编程。 4、能够使用指针来操作内存中的数据。 5、能够使用文件来读取和写入数据。 三、实训内容 1、程序功能 本程序实现了一个简单的万年历功能,可以通过输入年份和月份来显示该月的日历。 2、程序实现 以下是本程序的主要代码实现: ```c #include <stdio.h> // 判断是否为闰年 int is_leap_year(int year) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { return 1; } else { return 0; } } // 获取某个月份的总天数 int get_days(int year, int month) { int days[] = {31, 28 + is_leap_year(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; return days[month - 1]; } // 获取某个日期是星期几 int get_weekday(int year, int month, int day) { if (month == 1 || month == 2) { year--; month += 12; } int c = year / 100; int y = year % 100; int w = y + y / 4 + c / 4 - 2 * c + 26 * (month + 1) / 10 + day - 1; w = (w % 7 + 7) % 7; return w; } // 显示日历 void show_calendar(int year, int month) { int days = get_days(year, month); int weekday = get_weekday(year, month, 1); printf(" 日 一 二 三 四 五 六\n"); int i; for (i = 0; i < weekday; i++) { printf(" "); } for (i = 1; i <= days; i++) { printf("%2d ", i); if ((weekday + i) % 7 == 0) { printf("\n"); } } if ((weekday + days) % 7 != 0) { printf("\n"); } } int main() { int year, month; printf("请输入年份:"); scanf("%d", &year); printf("请输入月份:"); scanf("%d", &month); if (month < 1 || month > 12) { printf("月份输入错误!\n"); return 1; } printf(" %d年%d月\n", year, month); show_calendar(year, month); return 0; } ``` 四、实训总结 通过本次实训,我学会了如何使用C语言来编写一个简单的万年历程序,巩固了C语言基本语法和编程思想,加强了对函数、数组、指针、文件等概念和用法的理解,提高了编程能力和解决问题的能力。同时,我也意识到在编程过程中需要注重代码的规范、可读性和可维护性,这对于日后的开发工作非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值