栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring MVC

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring MVC

入门案例 案例实现 步骤1
  • 导入坐标



  4.0.0

  org.example
  SpringMVC_text
  1.0-SNAPSHOT
  war


  
    UTF-8
    1.8
    1.8
  

  
    
      javax.servlet
      javax.servlet-api
      3.1.0
      provided
    
    
      javax.servlet.jsp
      jsp-api
      2.1
      provided
    
    
    
      org.springframework
      spring-context
      5.1.9.RELEASE
    
    
    
      org.springframework
      spring-web
      5.1.9.RELEASE
    
    
    
      org.springframework
      spring-webmvc
      5.1.9.RELEASE
    
  

  
    
      
        org.apache.tomcat.maven
        tomcat7-maven-plugin
        2.1
        
          80
          /
        
      
    
  

步骤2
  • 定义表现层业务处理器controller,并配置成spring的bean(等同于servlet)
package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    public String save(){
        System.out.println("user mvc controller is running ...... ");
    }
}
  • 该bean的处理需要使用独立的配置文件扫描(XML版)(spring-mvc.xml)


        
    


步骤3
  • web .xml中配置springMvc核心控制器,用于将请求转发到对应的具体业务处理器controller中(等同于servlet配置)


    
    
        DispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath*:spring-mvc.xml
        
    
    
        DispatcherServlet
        /
    


步骤4
  • 设定具体controller的访问路径(等同于servlet在web. xml中的配置)
package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    @RequestMapping("/save")
    public String save(){
        System.out.println("user mvc controller is running ...... ");
    }
}
步骤5
  • 设置返回页面
package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    @RequestMapping("/save")
    public String save(){
        System.out.println("user mvc controller is running ...... ");
        return "success.jsp";	
    }
}
入门案例工作流程分析
  • 服务器启动
    1. 加载web.xrn1中Dispatcherservlet
    2. 读取spring-mvc.xml中的配置,加载所有com.itheima包中所有标记为bean的类
    3. 读取bean中方法上方标注@RecuestMapping的内容
  • 处理请求
    1. DispatcherServlet配置拦截所有请求 /
    2. 使用请求路径与所有加载的@RecuestMapping的内容进行比对
    3. 执行对应的方法
    4. 根据方法的返回值在webapp目录中查找对应的页面并展示
SpringMVC 技术架构图
  • Dispatcherservlet:前端控制器,是整体流程控制的中心,由其调用其它组件处理用户的请求,有效的降低了组件间的耦合性
  • HardlerMapping:处理器映射器,负责根据用户请求找到对应具体的Handler处理器
  • Handler:处理器,业务处理的核心类,通常由开发者编写,描述具体的业务
  • HardlAdaptez:处理器适配器,通过它对处理器进行执行
  • View Resolver:视图解析器,将处理结果生成view视图
  • view:视图,最终产出结果,常用视图如jsp、 html
基础配置 Controller加载控制
  • SpringMVC的处理器对应的bean必须按照规范格式开发,为避免加入无效的bean可通过bean加载过滤器进行包含设定或排除设定,表现层bean标注通常设定为@Controller

在spring-mvc.xml文件中修改成


	

或者在SpringMVCConfig.java文件中修改成

package com.liu.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(
        value = "com.liu",
        includeFilters =
                @ComponentScan.Filter(
                        type = FilterType.ANNOTATION,
                        classes = {Controller.class}
                )
)
public class SpringMVCConfig {
}

静态资源加载控制
  • 核心控制器拦截的是所有请求,需要对静态资源请求进行放行,通过配置放行资源实现
 
  • 第二种(SpringMVC用ModelAndView参数会帮你注入ModelAndView对象)
@RequestMapping("/quick2")
public ModelAndView quickMethod2(ModelAndView modelAndView){
    modelAndView.addObject("username","liu");   //传值变量,index.jsp 页面显示
    // 设置视图名称
    modelAndView.setViewName("index");  //返回 /views/index.jsp 页面
    return modelAndView;
}
  • 第三种(用 Model 对象)
@RequestMapping("/quick3")
public String quickMethod3(Model model){
    model.addAttribute("username","liu");
    return "index";
}
回写数据(异步方式) 直接返回字符串
@RequestMapping("/quick4")
@ResponseBody    //不进行页面跳转(说明:直接回写数据方式返回)
public String quickMethod4(){
    return "不进行页面跳转(说明:直接回写数据方式返回)";
}
返回对象或集合

得先加入解析json字符串的坐标

	
	......

    
    
      com.fasterxml.jackson.core
      jackson-core
      2.9.0
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.9.0
    
    
      com.fasterxml.jackson.core
      jackson-annotations
      2.9.0
    

	......

返回对象

@RequestMapping("/quick4")
@ResponseBody    //不进行页面跳转(说明:直接回写数据方式返回)
public User quickMethod4(){
    User user=new User();
    user.setUsername("liu");
    user.setAge(28);
    return user;
}

返回集合

@RequestMapping("/quick5")
 @ResponseBody    //不进行页面跳转(说明:直接回写数据方式返回)
 public List quickMethod5(){
     User user1=new User();
     user1.setUsername("liu");
     user1.setAge(28);

     User user2=new User();
     user2.setUsername("xiu");
     user2.setAge(22);

     ArrayList arrayList=new ArrayList();
     arrayList.add(user1);
     arrayList.add(user2);
     return arrayList;
 }
异步请求响应

名称:@ResponseBody
类型:方法注解、返回值注解
位置:处理器类中的方法前方
作用:将异步提交数据组织成标准请求参数格式,并赋值给形参
范例:

@RequestMapping("/ajaxReturnString")
@ResponseBody
pubiic string ajaxReturnString(){
	system.out.printIn("controller return string ...");
	return "page.jsp";
)
跨域访问

当通过域名A下的操作访问域名B下的资源时,称为跨域访问

跨域访问的概念
  • 协议
  • 工P地址
  • 端口
  • 域名
@Crossorigin
  • 名称:@Crossorigin
  • 类型:方法注解、类注解
  • 位置:处理器类中的方法上方或类上方
  • 作用:设置当前处理器方法/处理器类中所有方法支持跨域访问
  • 范例:
@RequestMapping("/quick6")
@ResponseBody    //不进行页面跳转(说明:直接回写数据方式返回)
@CrossOrigin    //支持跨域访问
public User quickMethod6(){
    User user=new User();
    user.setUsername("liu");
    user.setAge(28);
    return user;
}
拦截器 拦截器简介
  • 拦截器(Interceptor)是一种动态拦截方法调用的机制
  • 作用:
    1. 在指定的方法调用前后执行预先设定后的的代码
    2. 阻止原始方法的执行
    3. 增强
  • 核心原理:AOP思想
  • 拦截器链:多个拦截器按照一定的顺序,对原始被调用功能进行增强
拦截器VS过滤器
  • 归属不同:Filter属于servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
自定义拦截器开发 自定义拦截器开发入门

创建 拦截器类

package com.liu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    // 前面
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置运行-------al");
        return true;  // 为 false 后面都不执行,包括 控制器(controller)也不执行
    }

    // 后面
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置运行-------bl");
    }

    // 完成后
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("完成后运行-------cl");
    }
}

在spring-mvc.xml里配置拦截器



    
        
        
    

    





    




    
    

    
    

    
    
        
            	
            	
        
    

拦截器配置与方法参数 方法参数
package com.liu.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    // 前面(参数处理,权限校验)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // HttpServletRequest request:请求
        // HttpServletResponse response:响应
        // Object handler:被拦截方法对象
        System.out.println("前置运行-------a1");
        return true;  // 为 false 后面都不执行,包括 控制器(controller)也不执行
    }

    // 后面(返回数据处理,修改返回的页面)
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // ModelAndView modelAndView: 返回的结果     作用:修改返回的页面
        System.out.println("后置运行-------b1");
    }

    // 完成后(处理异常)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Exception ex: 拦截的异常
        System.out.println("完成后运行-------c1");
    }
}
拦截器配置

    
        
                    
            
           

              

        
    

  • mapping标签:可以配置多个,支持通配符 *
    • *表示任意名称,/*仅表示根路径下任意名称,不再往下匹配目录
    • **表示当前路径及其子路径,/**表示根路径及其子路径下任意名称
  • exclude-mapping标签:用于剔除不符合要求的配置项,加速配置过程,支持通配符*
  • bean标签(ref标签)∶只能配置一个
多拦截器配置


    
         
        
    
	
	
             
        
    
    
	
        
        
    


执行顺序为

a1
a2
a3
我是方法
b3
b2
b1
c3
c2
c1

当 a2 为的返回值false时,执行顺序为

a1
a2
c1
拦截器链配置
  • 当配置多个拦截器时,形成拦截器链
  • 拦截器链的运行顺序参照配置的先后顺序
  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
责任链模式
  • 责任链模式是一种行为模式
  • 特征:
    • 沿着一条预先设定的任务链l顺序执行,每个节点具有独立的工作任务
  • 优势:
    • 独立性:只关注当前节点的任务,对其他任务直接放行到下一节点
    • 隔离性:具备链式传递特征,无需知晓整体链路结构,只需等待请求到达后进行处理即可
    • 灵活性:可以任意修改链路结构动态新增或删减整体链路责任
    • 解耦:将动态任务与原始任务解耦
  • 弊端:
    • 链路过长时,处理效率低下
    • 可能存在节点上的循环引用现象,造成死循环,导致系统崩溃
异常处理 通用异常处理方案

这个方案是在接受完参数后才工作的,所以接受参数是发生异常无法处理
创建异常处理类
只要继承 HandlerExceptionResolver 接口 和 @Component 报错对跳转到这个

package com.liu.exception;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class ExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView=new ModelAndView();

		// 根据异常的种类不同,进行分门别类的管理,返回不同的信息
        if (e instanceof  NullPointerException){
            modelAndView.addObject("msg","空指针异常");
        }else if (e instanceof ArithmeticException){
            modelAndView.addObject("msg","算数运算异常");
        }else {
            modelAndView.addObject("msg","未知的异常");
        }

        modelAndView.setViewName("error.jsp");
        return modelAndView;
    }
}
使用注解实现异常分类管理(推荐用这个)

注解方式工作比较早,在Controller形成前就工作了,所以能处理接受参数时发生异常

  • 名称:@ControllerAdvice
  • 类型:类注解
  • 位置:异常处理器类上方
  • 作用:设置当前类为异常处理器类
  • 范例:
@Component
@ControllerAdvice
public class ExceptionAdvice {}
package com.liu.exception;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Component
@ControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler(NullPointerException.class)
    @ResponseBody       // 不返回页面
    public String doNullException(Exception ex){
        return "空指针异常------";
    }

    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody       // 不返回页面
    public String doArithmeticException(Exception ex){
        return "算数异常------";
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody       // 不返回页面
    public String doException(Exception ex){
        return "未知异常------";
    }
}
项目异常处理方案
  • 异常分类

    • 业务异常:
      • 规范的用户行为产生的异常
      • 不规范的用户行为操作产生的异常
    • 系统异常:
      • 项目运行过程中可预计且无法避免的异常
    • 其他异常:
      • 编程人员未预期到的异常
  • 异常处理方案

    • 业务异常:
      • 发送对应消息传递给用户,提醒规范操作
    • 系统异常:
      • 发送固定消息传递给用户,安抚用户
      • 发送特定消息给运维人员,提醒维护
      • 记录日志
    • 其他异常:
      • 发送固定消息传递给用户,安抚用户
      • 发送特定消息给编程人员,提醒维护
        • 口纳入预期范围内
      • 记录日志
实现方案
  • 因为有太多的异常不可能都处理,一个一个写有太麻烦了
  • 所以可以创建 三个自定义异常方案:
用户行为异常类:返回用户相关的异常

创建用户行为异常类BusinessException

package com.liu.exception;

public class BusinessException extends RuntimeException {
    public BusinessException() {
    }

    public BusinessException(String message) {
        super(message);
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }

    public BusinessException(Throwable cause) {
        super(cause);
    }

    public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

把用户相关错误行为 都用这个类来接受(相当于中间机制)

if(user.getName().trim( ).length()< 8){
	throw new BusinessException("对不起,用户名长度不满足要求,话重新输入");
}
if(user.getAge() < 0) {
	throw new BusinessException("对不起,年龄必须是o到100之间的数字!");
}
系统异常类:返回用户相关的异常

创建系统异常类SystemException

package com.liu.exception;

public class SystemException extends RuntimeException {
    public SystemException() {
    }

    public SystemException(String message) {
        super(message);
    }

    public SystemException(String message, Throwable cause) {
        super(message, cause);
    }

    public SystemException(Throwable cause) {
        super(cause);
    }

    public SystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

在发生系统级错误用于接受,进行统一处理(如:告诉用户系统出错、告诉运维人员就行维护,进行日志写入等)

try {
	//模拟连接数据库连接失败时
    throw new SQLException();
} catch (SQLException e) {
    throw new SystemException("数据库连接超时!",e);
}
项目错误处理类(用于处理接受到的用户行为异常类错误和系统异常类错误)
package com.liu.exception;

import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Component
@ControllerAdvice
public class ProjectExceptionAdvice {

    @ExceptionHandler(BusinessException.class)
    public String doBusinessException(Exception ex, Model m){
        m.addAttribute("msg",ex.getMessage());
        return "error.jsp";
    }

    @ExceptionHandler(SystemException.class)
    public String doSystemException(Exception ex, Model m){
        m.addAttribute("msg","服务器连接失败请联系管理员!");

        //实际的问题显现更应该传递给redis服务器,运维人员通过后台系统查看

        return "error.jsp";
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody       // 不返回页面
    public String doException(Exception ex, Model m){
        m.addAttribute("msg",ex.getMessage());
        
        // 将ex对象保存起来
        
        return "error.jsp";
    }
}
实用技术 文件上传下载 MultipartResolver接口
  • MultipartResolver接口定义了文件上传过程中的相关操作,并对通用性操作进行了封装
    • MultipartResolver接口底层实现类CommonsMultipartResovler
    • CommonsMultipartResovler并未自主实现文件上传下载对应的功能,而是调用了apache的文件上传下载组件

	commons-fileupload
	commons-fileupload
	1.4

实现 (在maven配置文件pom.xml)导入坐标
	......
	
    
    
      commons-fileupload
      commons-fileupload
      1.4
    
    
	......
(在SpringMVC配置文件spring-mvc.xml)配上文件上传下载接口
    
    
        
    
在控制器中

上传文件的input标签中的name名要对应 控制器 接受参数时的变量名

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


上传LOGO:
package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Controller
public class FileUploadController {
    @RequestMapping("/fileupload")
    public String fileupload(MultipartFile file) throws IOException {
        // 上传文件方法
        file.transferTo(new File("abc.png"));
        return "page.jsp";
    }
}
服务器上传文件注意事项
  • 文件命名问题,获取上传文件名,并解析文件名与扩展名
    file.getoriginalFilename()
  • 文件名过长问题
  • 文件保存路径
ServletContext context = request.getServletContext();
String basePath = context.getRealPath("/uploads");
File file = new File(basePath+"/");
if(!file.exists())file.mkdirs();
  • 重名问题
String uuid = UUID.randomUUID().toString().replace("-","").toUpperCase();

案例:文件路径和多文件上传

package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;

@Controller
public class FileUploadController {
    @RequestMapping("/fileupload")
    public String fileupload(MultipartFile file,MultipartFile file1,MultipartFile file2, HttpServletRequest request) throws IOException {

//        System.out.println(file.getSize());             // 文件大小
//        System.out.println(file.getBytes());            // 可以用于写文件
//        System.out.println(file.getContentType());      // 类型
//        System.out.println(file.getName());             // 是 input 的 name
//        System.out.println(file.getOriginalFilename()); // 文件名称
//        System.out.println(file.isEmpty());             // 是否为空

        if (!file.isEmpty()){
            String fileName=file.getOriginalFilename();
            // 设置保存的路径
            String realPath = request.getServletContext().getRealPath("/images");
            file.transferTo(new File(realPath,fileName));
        }
        if (!file1.isEmpty()){
            String fileName=file1.getOriginalFilename();
            // 设置保存的路径
            String realPath = request.getServletContext().getRealPath("/images");
            file1.transferTo(new File(realPath,fileName));
        }
        if (!file2.isEmpty()){
            String fileName=file2.getOriginalFilename();
            // 设置保存的路径
            String realPath = request.getServletContext().getRealPath("/images");
            file2.transferTo(new File(realPath,fileName));
        }
        return "page.jsp";
    }
}
Restful Rest
  • Rest (REpresentational state Transfer)一种网络资源的访问风格,定义了网络资源的访问方式

    • 传统风格访问路径
      • http://localhost/user/get?id=1
      • http://localhost/deleteuser?id=1
    • Rest风格访问路径
      • http://localhost/user/1
  • Restful是按照Rest风格访问网络资源

  • 优点

    • 隐藏资源的访问行为,通过地址无法得知做的是何种操作
    • 书写简化
Rest行为约定方式
  • GET(查询) http://localhost/user/1 GET
  • POST(保存) http://localhost/user POST
  • PUT (更新) http://localhost/user PUT
  • DELETE(删除) http://localhost/user DELETE

注意:上述行为是约定方式,约定不是规范,可以打破,所以称rest风格,而不是Rest规范

Restful开发入门
  • SpringMvc支持Restful

    • 请求路径访问配置发生变化
      • 控制器定义方式发生变化
      • 页面调用方式发生变化
  • Restful规范主要用于前后端分离的项目

package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {
    @RequestMapping("/user/{id}")
    @ResponseBody
    public String restLocation(@PathVariable Integer id){
        System.out.println("我是UserController--------------get:"+id);
        return "page.jsp";
    }
}
  • 简化
package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

//@Controller
//@ResponseBody
@RestController         //这句相当于上面的合并
@RequestMapping("/user/")
public class UserController {

    @RequestMapping("{id}")
    public String restLocation(@PathVariable Integer id){
        System.out.println("我是UserController--------------get:"+id);
        return "page.jsp";
    }
}
  • 由于Restful入门开发不知道你要操作什么,所以要加上访问行为
    配置web.xml让SpringMVC支持PUT和DELETE请求行为


  
  
    characterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
      encoding
      UTF-8
    
  
  
    characterEncodingFilter
    /*
  

  
  
    hiddenHttpMethodFilter
    org.springframework.web.filter.HiddenHttpMethodFilter
  
  
    hiddenHttpMethodFilter
    DispatcherServlet
  
  
  
    DispatcherServlet
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath*:spring-mvc.xml
    
  
  
    DispatcherServlet
    /
  


在控制器里写

package com.liu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

//@Controller
//@ResponseBody
@RestController         //这句相当于上面的合并
@RequestMapping("/user/")
public class UserController {
//    @RequestMapping(value = "{id}",method = RequestMethod.GET)
    @GetMapping("{id}")     //等于上面的那句话
    public String get(@PathVariable Integer id){
        System.out.println("我是UserController--------------get:"+id);
        return "page.jsp";
    }

//    @RequestMapping(value = "{id}",method = RequestMethod.POST)
    @PostMapping("{id}")     //等于上面的那句话
    public String post(@PathVariable Integer id){
        System.out.println("我是UserController--------------post:"+id);
        return "page.jsp";
    }

//    @RequestMapping(value = "{id}",method = RequestMethod.PUT)
    @PutMapping("{id}")     //等于上面的那句话
    public String put(@PathVariable Integer id){
        System.out.println("我是UserController--------------put:"+id);
        return "page.jsp";
    }

//    @RequestMapping(value = "{id}",method = RequestMethod.DELETE)
    @DeleteMapping("{id}")     //等于上面的那句话
    public String delete(@PathVariable Integer id){
        System.out.println("我是UserController--------------delete:"+id);
        return "page.jsp";
    }
}
postman

一款可以发送Restful风格请求的工具,方便开发调试。首次运行需要联网注册

表单校验 表单校验框架
  • JSR (Java Specification Requests):Java规范提案
    • 303:提供bean属性相关校验规则
  • JCP (Java comnunity Process):Java社区
  • Hibernate框架中包含一套独立的校验框架hibernate-validator

	org.hibernate
	hibernate-validator
	6.1.0.Final

注意:6版本以上要 tomcat8.5 以上的版本

入门案例 步骤一:加入相关坐标
	......

    
    
      javax.validation
      validation-api
      2.0.1.Final
    

    
    
      org.hibernate
      hibernate-validator
      6.1.0.Final
    

	......
步骤二:在控制器方法参数上加 @Valid 验证注解
package com.liu.controller;

import com.liu.domain.Employee;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;

@Controller
public class EmployeeController {

    @RequestMapping("/addemployee")
    public String addEmployee(@Valid Employee employee){
        return "success.jsp";
    }
}
步骤三:在实体类里判断验证
package com.liu.domain;

import javax.validation.constraints.NotBlank;

public class Employee {
    @NotBlank(message = "姓名不能为空")
    private String name;

    private Integer age;

	......
}
步骤四:在控制器方法里接收判断并返回给页面
package com.liu.controller;

import com.liu.domain.Employee;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@Controller
public class EmployeeController {

    @RequestMapping("/addemployee")
    public String addEmployee(@Valid Employee employee, Errors errors, Model model){
        if (errors.hasErrors()){    // 条件是否成立
            List fieldErrors = errors.getFieldErrors();   // 条件成立所有对象
            for (FieldError error :fieldErrors){
                
//                System.out.println(error.getField());
//                System.out.println(error.getDefaultMessage());
                
                // 封装返回页面
                model.addAttribute(error.getField(),error.getDefaultMessage());
            }
            return "addemployee.jsp";
        }
        return "success.jsp";
    }
}
实际的校验规则
  • 同一个字段有多个约束条件
  • 引用类型字段如何校验
  • 根据业务不同需要调整是否参与校验
校验器
  • 同一个属性可以添加多个校验器
@NotNull(message="请输入您的年龄")
@Max(value=60,message="年龄最大值不允许超过60岁")
@Min(value=18,message="年龄最小值不允许低于18岁")
private Integer age;// 员工年龄
  • 3种判定空校验器的区别
表单数据@NotNull@NotEmpty@NotBlank
String s=nullfalsefalsefalse
String s=""truefalsefalse
String s=" "truetruefalse
String s=“Jock”truetruetrue
具体案例 前端页面
员工姓名:${name}
员工年龄:${age}
省:${requestScope['address.provinceName']}
实体类

实体类Employee.java

package com.liu.domain;

import com.liu.controller.groups.GroupA;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

public class Employee {
    @NotBlank(message = "姓名不能为空",groups = {GroupA.class})	// groups 分组
    private String name;

    @NotNull(message = "请输入您的年龄",groups = {GroupA.class})
    @Max(value = 60,message = "不能超过60")
    @Min(value = 18,message = "不能小于18")
    private Integer age;

    @Valid  // 嵌套校验加上这个,这个对象的校验,在自己里面做
    private Address address;

	......
}

实体类Address.java

package com.liu.domain;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;

public class Address implements Serializable {
    @NotBlank(message = "请输入省份名称")
    private String ProvinceName;

    @NotBlank(message = "请输入城市名称")
    private String cityName;

    @NotBlank(message = "请输入详细地址")
    private String detail;

    @NotBlank(message = "请输入邮政编码")
    @Size(max = 6,min = 6,message = "邮政编码由6位组成")
    private String zipCode;

	......
}
分组接口
package com.liu.controller.groups;

public interface GroupA {
}
控制器
package com.liu.controller;

import com.liu.controller.groups.GroupA;
import com.liu.domain.Employee;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@Controller
public class EmployeeController {

	//@Validated 支持分组
    @RequestMapping("/addemployee")
    public String addEmployee(@Validated({GroupA.class}) Employee employee, Errors errors, Model model){
        if (errors.hasErrors()){    // 条件是否成立
            List fieldErrors = errors.getFieldErrors();   // 条件成立所有对象
            for (FieldError error :fieldErrors){

//                System.out.println(error.getField());
//                System.out.println(error.getDefaultMessage());

                // 封装返回页面
                model.addAttribute(error.getField(),error.getDefaultMessage());
            }
            return "addemployee.jsp";
        }
        return "success.jsp";
    }

	// @Valid 不支持分组
    @RequestMapping("/addemployee2")
    public String addEmployee2(@Valid Employee employee, Errors errors, Model model){
        if (errors.hasErrors()){
            List fieldErrors = errors.getFieldErrors();
            for (FieldError error :fieldErrors){
                model.addAttribute(error.getField(),error.getDefaultMessage());
            }
            return "addemployee.jsp";
        }
        return "success.jsp";
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/301727.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号