发表于: 2019-11-21 22:43:27

2 1449


啥也不说就是干!!!

今天完成的事情:

1、SpringMVC 异常处理

SpringMVC 在处理请求过程中出现异常信息将会交给异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑

异常通常包含编译时异常和运行时异常

运行时异常,比如:空指针异常、数组越界异常

编译时异常,比如:数据库异常、文件读取异常、自定义异常。对于这样的异常必须使用try catch 代码块或 throws 关键字进行异常处理。

系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 SpringMVC 前端控制器交由异常处理器进行异常处理:

全局范围内只有一个异常处理器。

自定义异常类:为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果 Controller、service、dao 抛出此类异常说明系统预期处理的异常信息。

public class CustomException extends Exception {
   private String message;
   public CustomException(String message) {
       super(message);
       this.message = message;
   }

   public String getMessage() {
       return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }

}

自定义异常处理器 GlobalExceptionHandler

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler{

       private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
       /**
        * 400 - Bad Request
        */
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       @ExceptionHandler(HttpMessageNotReadableException.class)
       public Result<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
           logger.error("参数解析失败", e);
           return Result.failed("could_not_read_json");
       }

        /**
        * 405 - Method Not Allowed
        */
       @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
       @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
       public Result<String> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
           logger.error("不支持当前请求方法", e);
           return Result.failed("request_method_not_supported");
       }

      /**
        * 415 - Unsupported Media Type
        */
      @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
      @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
      public Result<String> handleHttpMediaTypeNotSupportedException(Exception e) {
           logger.error("不支持当前媒体类型", e);
           return Result.failed("content_type_not_supported");
       }

       /**
        * 500 - Internal Server Error
        */
       @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
       @ExceptionHandler(Exception.class)
       public Result<String> handleException(Exception e) {
           if (e instanceof CustomException){
              return Result.failed(e.getMessage());
           }

           logger.error("服务运行异常", e);
           e.printStackTrace();
           return Result.failed("server_error");
       }

}

2、SpringMVC 参数校验

为了避免用户绕过浏览器,使用http工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中,同时也可以避免恶意请求,Spring的 javax.validation 注解式参数校验可以很好的帮助我们实现对参数的校验

1)什么是 javax.validation

JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面(面向注解编程的时代),就可以在需要校验的时候进行校验了

2)添加相关依赖:

3)常用注解说明:

验证注解
验证的数据类型
说明
@AssertFalse
boolean,Boolean
验证注解的元素值false
@AssertTrue
boolean,Boolean
验证注解的元素值是true
@NotNull
任意类型
验证注解的元素值不是 null
@Null
任意类型
验证注解的元素值是 null
@Min(value=值)
short,int,long,Number(数字类型)
验证注解的元素值大于等于@Min指定的value值
@Max(value=值)
和@Min要求一样
验证注解的元素值小于等于@Max指定的value值
@Past
日期类型
验证注解的元素值(日期类型)比当前时间早
@Future
与@Past要求一样
验证注解的元素值(日期类型)比当前时间晚
@NotBlank
CharSequence子类型
验证注解的元素值不为空(不为null、去除首位空格后长度为0)
@Length(min=下限, max=上限)
CharSequence子类型
验证注解的元素值长度在min和max区间内
@NotEmpty
CharSequence子类型、Collection、Map、数组
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Email(regexp=正则表达式,flag=标志的模式)
CharSequence子类型(如String)
验证注解的元素值是Email

4)项目中的使用:

@Validated 声明要检查的参数(Controller 方法入参)

@RequestMapping(value "/",method = RequestMethod.POST)
@ResponseBody
public Result<Integer> addStudentInfo(@Validated Student student){
int id = studentService.addStudent(student);
   String msg = "";
   if(id>0){
       msg="插入成功";
   }
   else{
       msg="插入失败";
   }
    return Result.success(id,msg);
}

对参数的字段进行注解标注:

@Data

public class Student {

   private int id;
   @NotBlank(message "用户名不能为空")
   private String name;
   @NotBlank(message "学号不能为空")
   private String onlineNum;
   @NotBlank(message "修真类型不能为空")

   private String jnshuType;

}

在全局异常处理中添加校验异常

MethodArgumentNotValidException 是绑定参数校验的异常,需要在SpringMVC 中处理,还需要对 ConstraintViolationException 异常进行处理

@ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
public Result<String> validationExceptionHandler(Exception exception) {
   BindingResult bindResult = null;
   if (exception instanceof BindException) {
       bindResult = ((BindException) exception).getBindingResult();
   } else if (exception instanceof MethodArgumentNotValidException) {
       bindResult = ((MethodArgumentNotValidException) exception).getBindingResult();
   }
   String msg;
   if (bindResult != null && bindResult.hasErrors()) {
       msg = bindResult.getAllErrors().get(0).getDefaultMessage();
       if (msg.contains("NumberFormatException")) {
           msg = "参数类型错误!";
       }
   }else {
       msg = "系统繁忙,请稍后重试...";
   }
   return Result.failed(-1, msg);
}

可以看到如果用户名传空值的话,请求如下:


3、前端页面之增删改查

查询学生信息列表(分页)

StudentController 查询学生信息方法:

@RequestMapping(value = "/",method = RequestMethod.GET)
public String getStudentList(Model model, @RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "10") int pageSize){
PageInfo<Student> pageInfo = studentService.getStudentList(pageNum,pageSize);
   model.addAttribute("pageInfo",pageInfo);
   return "student_list";
}

学生信息列表页面 student_list.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>monkey1024</title>
   <link href="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet">

</head>
<body>
<div class="container theme-showcase" role="main">

   <div class="page-header">
       <a id="add" type="button" class="btn btn-sm btn-success" href="${pageContext.request.contextPath}/jsp/student_add.jsp">添加</a>
   </div>
   <div class="row">
       <div class="">
           <table class="table table-striped">
               <thead>
               <tr>
                   <th>编号</th>
                   <th>姓名</th>
                   <th>QQ</th>
                   <th>修真类型</th>
                   <th>毕业学校</th>
                   <th>学号</th>
                   <th>辅导师兄</th>
                   <th>口号</th>
                   <th>操作</th>
               </tr>
               </thead>
               <tbody>
                  <c:forEach items="${pageInfo.list}" var="stu">
                     <tr>
                       <td>${stu.id}</td>
                       <td>${stu.name}</td>
                       <td>${stu.qq}</td>
                       <td>${stu.jnshuType}</td>
                       <td>${stu.school}</td>
                       <td>${stu.onlineNum}</td>
                       <td>${stu.counsellor}</td>
                       <td>${stu.slogan}</td>
                       <td>
                           <a type="button" class="btn btn-sm btn-warning" href="${pageContext.request.contextPath}/jsp/student_update.jsp?id=${stu.id}&slogan=${stu.slogan}">修改</a>
                           <form action="${pageContext.request.contextPath}/student/${stu.id}" method="post" >
                               <input name="_method" type="hidden" value="DELETE">
                               <input type="submit" class="btn btn-sm btn-info" value="删除">
                           </form>
                       </td>
                   </tr>
                 </c:forEach>
           </tbody>
           </table>
           <table border="0" cellspacing="0" cellpadding="0" width="900px">
               <tr>
                   <td class="td2">
                       <span>${pageInfo.pageNum}/ ${pageInfo.pages}</span>&nbsp;&nbsp;
                       <span>总记录数:${pageInfo.total}&nbsp;&nbsp;每页显示:${pageInfo.pageSize}</span>&nbsp;&nbsp;
                       <span>
                         <c:if test="${pageInfo.pageNum != 5}">
                            <a href="${pageContext.request.contextPath }/student/">[首页]</a>&nbsp;&nbsp;
                            <a href="${pageContext.request.contextPath }/student/?pageNum=${pageInfo.pageNum-1}">[上一页]</a>&nbsp;&nbsp;
                         </c:if>

                         <c:if test="${pageInfo.pageNum != pageInfo.total}">
                            <a href="${pageContext.request.contextPath }/student/?pageNum=${pageInfo.pageNum+1}">[下一页]</a>&nbsp;&nbsp;
                            <a href="${pageContext.request.contextPath }/student/?pageNum=${pageInfo.total}">[尾页]</a>&nbsp;&nbsp;
                         </c:if>
                       </span>
                   </td>
               </tr>
           </table>
       </div>
   </div>
</div>
<script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</body>
</html>

浏览器发送请求:http://localhost:8080/JnshuTask2/student/,看到页面效果如下:

添加学生信息

StudentController 新增学生信息方法:

@RequestMapping(value = "/",method = RequestMethod.POST)
public String addStudentInfo(@Validated Student student){
int id = studentService.addStudent(student);
   return "redirect:/student/";
}

新增学生信息页面 student_add.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>monkey1024</title>
   <link href="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="page-header"></div>
<div class="container">
   <form action="${pageContext.request.contextPath}/student/" method="post" style="max-width: 330px;padding: 15px;margin: 0 auto;">
       <div class="form-group">
           <label for="name">姓名:</label>
           <input type="text" class="form-control" id="name" name="name">
       </div>
       <div class="form-group">
           <label for="qq">qq:</label>
           <input type="text" class="form-control" id="qq" name="qq">
       </div>
       <div class="form-group">
           <label for="school">毕业学校:</label>
           <input type="text" class="form-control" id="school" name="school">
       </div>
       <div class="form-group">
           <label for="jnshuType">修真类型:</label>
           <input type="text" class="form-control" id="jnshuType" name="jnshuType">
       </div>
       <div class="form-group">
           <label for="onlineNum">学号:</label>
           <input type="text" class="form-control" id="onlineNum" name="onlineNum">
       </div>

       <div class="form-group">
           <label for="counsellor">辅导师兄:</label>
           <input type="text" class="form-control" id="counsellor" name="counsellor">
       </div>
       <div class="form-group">
           <label for="slogan">口号:</label>
           <input type="text" class="form-control" id="slogan" name="slogan">
       </div>
       <input type="submit" value="提交">
   </form>
</div>
<script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</body>
</html>

修改学生信息

StudentController 修改学生信息方法:

@RequestMapping(value = "/{id}",method = RequestMethod.PUT)
public String updateSlogan(@PathVariable Integer id,String slogan){
int row = studentService.updateSloganById(id,slogan);
   return "redirect:/student/";

}

修改学生信息页面 student_update.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>monkey1024</title>
   <link href="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="page-header"></div>
<div class="container">
   <form action="${pageContext.request.contextPath}/student/${param.id}" method="post" style="max-width: 330px;padding: 15px;margin: 0 auto;">
       <input name="id" type="hidden" value="${param.id}">
       <input name="_method" type="hidden" value="PUT">
       <div class="form-group">
           <label for="slogan">口号:</label>
           <input type="text" class="form-control" id="slogan" name="slogan" value="${param.slogan}">
       </div>
       <input type="submit" value="修改">
   </form>
</div>
<script src="${pageContext.request.contextPath}/static/jquery-3.3.1.min.js"></script>
<script src="${pageContext.request.contextPath}/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</body>
</html>

修改成功,重定向到 student_list.jsp

删除学生信息 

StudentController 删除学生信息方法:

@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
public String deleteStudentInfo(@PathVariable Integer id){
int row = studentService.deleteStudentById(id);
   return "redirect:/student/";

}

删除成功重定向至 student_list.jsp

由于 form 表单不支持 PUT DELETE 方法的提交,

所以需要在 web.xml 配置文件中配置相关的过滤器,使得 POST 请求 可以转化为 PUT DELETE 请求

 <!--配置 HiddenHttpMethodFilter: 把 POST 请求转为 DELETE、PUT 请求 -->
<filter>
   <filter-name>HttpMethodFilter</filter-name>
   <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>HttpMethodFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

并且 <input> 标签还需要设置 _method hidden 域

明天计划的事情:

1、项目部署至 远程服务器(tomcat)

2、学习配置 Nginx

遇到的问题:


收获:

SpringMVC 参数校验及全局异常处理


返回列表 返回列表
评论

    分享到