概述 核心概述 包类的自动扫描(AutoScan) 依赖注入(IoC) 方法拦截(AOP) 记录类属性状态 (PropertyState) 事件服务(Event) 模块(Module) 国际化(I18N) Lang 配置体系概述 配置体系目录结构及配置 示例一:解析XML配置 示例二:解析Properties配置 配置体系模块更多操作 日志概述 日志模块配置 使用示例 JDBC持久化概述及模块配置 数据源(DataSource) 数据实体(Entity) 自动生成实体类(方式一) 自动生成实体类(方式二) 事务(Transaction) 会话(Session) 数据实体操作 结果集(ResultSet) 查询(Query) 存储器(Repository) 高级特性—多表查询及自定义结果集数据处理 高级特性—存储过程调用与结果集数据处理 高级特性—数据库锁操作 插件概述 插件工厂 自定义插件工厂 插件结构 插件的实现及使用 服务概述 服务端(Server)示例 客户端(Client)示例 客户端和服务端对象的使用 验证概述 默认验证器及参数说明 默认国际化资源文件内容 验证框架使用示例 自定义验证器 缓存概述 缓存模块配置 缓存模块使用示例 WebMVC概述 模块初始化及配置说明 控制器(Controller) 控制器参数(Parameter) 环境上下文对象(WebContext) 文件上传(Upload) 视图(View) 验证(Validation) 缓存(Cache) 拦截器(Intercept) Cookies操作 国际化(I18N) 约定模式(Convention Mode) 高级特性—控制器请求处理器 高级特性—异常错误处理器

概述

YMP在线手册

浏览13637
更新时间2022-04-11

WebMVC模块不但让编写控制器变得非常简单,处理请求参数也变得更加容易!WebMVC会根据控制器方法参数或类成员的注解配置,自动转换与方法参数或类成员对应的数据类型,参数的绑定涉及以下注解:

基本参数注解
  • @RequestParam:绑定请求中的参数;

  • @RequestHeader:绑定请求头中的参数变量;

  • @CookieVariable:绑定Cookie中的参数变量;

上面三个注解拥有相同的参数:

value:参数名称,若未指定则默认采用方法参数变量名;

prefix:参数名称前缀,默认为"";

defaultValue:指定参数的默认值,默认为"";

示例代码:

    @Controller
    @RequestMapping("/demo")
    public class DemoController {

        @RequestMapping("/param")
        public IView testParam(@RequestParam String name,
                          @RequestParam(defaultValue = "18") Integer age,
                          @RequestParam(value = "name", prefix = "user") String username,
                          @RequestHeader(defaultValue = "BASIC") String authType,
                          @CookieVariable(defaultValue = "false") Boolean isLogin) {

            System.out.println("AuthType: " + authType);
            System.out.println("IsLogin: " + isLogin);
            return View.textView("Hi, " + name + ", UserName: " + username + ", Age: " + age);
        }
    }

通过浏览器访问URL测试:

    http://localhost:8080/demo/param?name=webmvc&user.name=ymper

执行结果:

    控制台输出:
    AuthType: BASIC
    IsLogin: false

    浏览器输出:
    Hi, webmvc, UserName: ymper, Age: 18
特别的参数注解
  • @PathVariable:绑定请求映射中的路径参数变量;

    value:参数名称,若未指定则默认采用方法参数变量名;

    示例代码:

    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/path/{name}/{age}")
        public IView testPath(@PathVariable String name,
                          @PathVariable(value = "age") Integer age,
                          @RequestParam(prefix = "user") String sex) {
    
            return View.textView("Hi, " + name + ", Age: " + age + ", Sex: " + sex);
        }
    }

    通过浏览器访问URL测试:

    http://localhost:8080/demo/path/webmvc/20?user.sex=F

    执行结果:

    Hi, webmvc, Age: 20, Sex: F

    注意:基于路径的参数变量必须是连续的,如:

    • 正确:/path/{name}/{age}

    • 错误:/path/{name}/age/{sex}

  • @ModelBind:值对象参数绑定注解;

    prefix:绑定的参数名称前缀,可选参数,默认为"";

    示例代码:

    public class DemoVO {
    
        @PathVariable
        private String name;
    
        @RequestParam
        private String sex;
    
        @RequestParam(prefix = "ext")
        private Integer age;
    
        // 省略Get和Set方法
    }
    
    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/bind/{demo.name}")
        public IView testBind(@ModelBind(prefix = "demo") DemoVO vo) {
            String _str = "Hi, " + vo.getName() + ", Age: " + vo.getAge() + ", Sex: " + vo.getSex();
            return View.textView(_str);
        }
    }

    通过浏览器访问URL测试:

    http://localhost:8080/demo/bind/webmvc?demo.sex=F&demo.ext.age=20

    执行结果:

    Hi, webmvc, Age: 20, Sex: F
  • @ParameterEscape:控制器方法参数转义注解;

    可以通过WebMVC模块配置参数parameter_escape_order设定是在控制器方法参数执行验证之前还是之后执行参数转义动作,参数取值范围为beforeafter,默认为after即参数验证之后进行转义;

    scope:字符串参数转义范围,默认为Type.EscapeScope.DEFAULT;

    • 取值范围包括:JAVA, JS, HTML, XML, SQL, CSV, DEFAULT;
    • 默认值DEFAULT,它完成了对SQL和HTML两项转义;

    skiped:通知父级注解当前方法或参数的转义操作将被忽略,默认为false;

    processor:自定义字符串参数转义处理器;

    • 可以通过IParameterEscapeProcessor接口实现自定义的转义逻辑;
    • 默认实现为DefaultParameterEscapeProcessor;

    示例代码一:

    @Controller
    @RequestMapping("/demo")
    @ParameterEscape
    public class DemoController {
    
        @RequestMapping("/escape")
        public IView testEscape(@RequestParam String content,
                                @ParameterEscape(skiped = true) @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }
    
    // 或者:(两段代码执行结果相同)
    
    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/escape")
        @ParameterEscape
        public IView testEscape(@RequestParam String content,
                                @ParameterEscape(skiped = true) @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }

    通过浏览器访问URL测试:

    http://localhost:8080/demo/escape?content=<p>content$<br><script>alert("hello");</script></p>&desc=<script>alert("hello");</script>

    执行结果:(控制台输出)

    Content: &lt;p&gt;content$&lt;br&gt;&lt;script&gt;alert(&quot;hello&quot;);&lt;/script&gt;&lt;/p&gt;
    Desc: <script>alert("hello");</script>

    示例一说明:

    • 由于控制器类被声明了@ParameterEscape注解,代表整个控制器类中所有的请求参数都需要被转义,因此参数content的内容被成功转义;
    • 由于参数desc声明的@ParameterEscape注解中skiped值被设置为true,表示跳过上级设置,因此参数内容未被转义;

    示例代码二:

    @Controller
    @RequestMapping("/demo")
    @ParameterEscape
    public class DemoController {
    
        @RequestMapping("/escape2")
        @ParameterEscape(skiped = true)
        public IView testEscape2(@RequestParam String content,
                                @ParameterEscape @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }

    通过浏览器访问URL测试:

    http://localhost:8080/demo/escape2?content=<p>content$<br><script>alert("hello");</script></p>&desc=<script>alert("hello");</script>

    执行结果:(控制台输出)

    Content: <p>content$<br><script>alert("hello");</script></p>
    Desc: &lt;script&gt;alert(&quot;hello&quot;);&lt;/script&gt;

    示例二说明:

    • 虽然控制器类被声明了@ParameterEscape注解,但控制器方法通过skiped设置跳过转义,这表示被声明的方法参数内容不进行转义操作,因此参数content的内容未被转义;
    • 由于参数desc声明了@ParameterEscape注解,表示该参数需要转义,因此参数内容被成功转义;

    注意:当控制器类和方法都声明了@ParameterEscape注解时,则类上声明的注解将视为无效;

非单例控制器的特殊用法

单例控制器与非单例控制器的区别:

  • 单例控制器类在WebMVC模块初始化时就已经实例化;
  • 非单例控制器类则是在每次接收到请求时都将创建实例对象,请求结束后该实例对象被释放;

基于以上描述,非单例控制器是可以通过类成员来接收请求参数,示例代码如下:

@Controller(singleton = false)
@RequestMapping("/demo")
public class DemoController {

    @RequestParam
    private String content;

    @RequestMapping("/sayHi")
    public IView sayHi(@RequestParam String name) {
        return View.textView("Hi, " + name + ", Content: " + content);
    }
}

通过浏览器访问URL测试:

http://localhost:8080/demo/sayHi?name=YMPer&content=Welcome!

此示例代码的执行结果:

Hi, YMPer, Content: Welcome!

注意:在单例模式下,WebMVC模块将忽略为控制器类成员赋值,同时也建议在单例模式下不要使用成员变量做为参数,在并发多线程环境下会发生意想不到的问题!!

相关视频

更多

免费

php8,我来也
初级php8,我来也

34万次学习

收藏

免费

Thinkphp6.0正式版视频教程
中级Thinkphp6.0正式版视频教程

39.6万次学习

收藏

免费

细说PHP第一季
中级细说PHP第一季

31万次学习

收藏

精品课程

更多
前端入门_HTML5
前端入门_HTML5

共29课时

64.9万人学习

CSS视频教程-玉女心经版
CSS视频教程-玉女心经版

共25课时

41.2万人学习

JavaScript极速入门_玉女心经系列
JavaScript极速入门_玉女心经系列

共43课时

76.6万人学习

独孤九贱(1)_HTML5视频教程
独孤九贱(1)_HTML5视频教程

共25课时

64.1万人学习

独孤九贱(2)_CSS视频教程
独孤九贱(2)_CSS视频教程

共22课时

24.3万人学习

独孤九贱(3)_JavaScript视频教程
独孤九贱(3)_JavaScript视频教程

共28课时

36.2万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时

133.1万人学习

热门下载

更多
phpStudy 2018最新版
phpStudy 2018最新版

集成PHP7,16种组合,超全大合集

下载

VC9 32位
VC9 32位

VC9 32位 phpstudy集成安装环境运行库

下载

VC11 32位
VC11 32位

VC11 32位 phpstudy集成安装环境运行库​

下载

php程序员工具箱完整版
php程序员工具箱完整版

程序员工具箱 v1.0 php集成环境

下载

VC14 32位
VC14 32位

VC14 32位 phpstudy安装环境运行库

下载

SublimeText3汉化版
SublimeText3汉化版

中文版,非常好用

下载

Notepad++ Windows版
Notepad++ Windows版

Notepad++ 8.9.7 Windows版官方安装包,适合 Windows 用户进行代码编辑、文本处理、语法高亮和插件扩展配置。

下载