• SpringMVC框架02——SpringMVC的Controller详解


    1、基于注解的控制器

    1.1、@Controller 注解类型

    在SpringMVC中使用org.springframework.stereotype.Controller注解类型声明某类的实例是一个控制器。
    代码示例:

    import org.springframework.stereotype.Controller;
    
    @Controller
    public class TestController {
    }

     在SpringMVC中使用扫描机制找到应用中所有基于注解的控制器类,需要在springmvc.xml配置文件中,配置<context:component-scan/>元素指定控制器类的包:

    <!--配置扫描控制器类-->
    <context:component-scan base-package="com.demo.controller"></context:component-scan>

    1.2、@RequestMapping 注解

    在基于注解的控制器类中可以为每个请求编写对应的处理方法,需要使用org.springframework.web.bind.annotation.RequestMapping注解类型将请求与处理方法一一对应。

    (1)方法级别注解
    代码如下:

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(){
            return "login";
        }
    }

     方法的返回值会自动解析为视图,需要在springmvc.xml中配置视图解析器,并指定前缀和后缀:

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置前缀-->
        <property name="prefix" value="/"></property>
        <!--配置后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

     用户可以使用如下URL方法login()方法:

    http://localhost:8080/项目/login
    在访问login方法之前需要事先在/WEB-INF/jsp/目录下创建login.jsp文件

    (2)类级别的注解
    代码如下:

    @Controller
    @RequestMapping("/index")
    public class TestController {
        @RequestMapping("/login")
        public String login(){
            return "login";
        }
    }

     用户可以使用如下URL方法login()方法:

    http://localhost:8080/项目/index/login

    1.3、请求处理

    请求处理方法中常出现的参数类型:

    • javax.servlet.http.HttpServletRequest
    • javax.servlet.http.HttpServletResponse
    • javax.servlet.http.HttpSession
    • 输入输出流
    • 表单实体类
    • 注解类型
    • org.springframework.ui.Model

    请求处理方法常见的返回类型:

    • String类型,表示逻辑视图,需要在springmvc.xml中配置视图解析器;
    • ModelAndView类型

    2、Controller接收请求参数的常见方式

    2.1、通过实体Bean接收请求

    通过一个实体Bean来接收请求参数,适用于get和post提交请求方式。需要注意的是,Bean的属性名称必须与请求参数名称相同。

    2.2、通过处理方法的形参接收请求

    直接把表单参数写到控制器类响应方法的形参中,即形参名称与请求参数名称完全相同,示例代码如下:
    jsp页面的form表单

    <form action="${pageContext.request.contextPath}/login" method="post">
        <p>
            用户名:<input type="text" name="uname">
        </p>
        <p>
            密码:<input type="password" name="upwd">
        </p>
        <p>
            <input type="submit" value="登录">
        </p>
    </form>

     controller类接收请求参数

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(String uname,String upwd) {
            //业务逻辑代码
            return "main";
        }
    }

    2.3、通过HttpServletRequest接收请求

    jsp页面代码参考本节第2点的form表单,controller类接收请求参数代码如下:

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(HttpServletRequest request) {
            String uname = request.getParameter("uname");
            String upwd = request.getParameter("upwd");
            //业务逻辑代码
            return "main";
        }
    }

    2.4、通过@PathVariable接收URL中的请求参数

    jsp页面代码参考本节第2点的form表单,controller类接收请求参数代码如下:

    @Controller
    public class TestController {
        @RequestMapping("/login/{uname}/{upwd}")
        public String login(@PathVariable String uname,@PathVariable String upwd) {
            //业务逻辑代码
            return "main";
        }
    }

     在访问“http://localhost:8080/login/admin/123456”路径时,上述代码自动将URL中的模板变量{uname}和{upwd}绑定到通过@PathVariable注解到同名参数上,即uname=admin,upwd=123456

    2.5、通过@RequestParam接收请求参数

    jsp页面代码参考本节第2点的form表单,controller类接收请求参数代码如下:

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(@RequestParam String uname, @RequestParam String upwd) {
            //业务逻辑代码
            return "index";
        }
    }

     该方式与本节第2点中提到的“通过处理方法的形参接收请求参数”的区别是:当请求参数与接收参数名不一致时,“通过处理方法的形参接收请求参数”不会报404错误,而“通过@RequestParam接收请求参数”会报404错误,提示效果如下:

    2.6、通过@ModelAttribute接收请求参数

    当@ModelAttribute注解放在处理方法的形参上时,用于将多个请求参数封装到一个实体对象,从而简化数据绑定流程,而且自动暴露为模型数据,在视图页面展示时使用。而直接以实体对象作为形参的方式接收请求参数,只是将多个请求参数封装到一个实体对象,并不能暴露为模型数据,需要使用model.addAttribute语句才能暴露为模型数据。
    创建实体类,代码示例如下:

    public class User {
        private String uname;
        private String upwd;
        //getter和setter方法
    }

     controller类,代码如下:

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(@ModelAttribute("user") User user) {
            //业务逻辑代码
            return "index";
        }
    }

    3、重定向与转发

    在SpringMVC框架中,控制器类中处理方法的return语句默认就是转发实现,只不过实现的是转发到视图,示例代码如下:

    @RequestMapping("/login")
    public String login() {
        //转发到index.jsp
        return "index";
    }

     在SpringMVC框架中,重定向与转发的示例代码如下:

    @Controller
    @RequestMapping("/index")
    public class TestController {
        @RequestMapping("/login")
        public String login() {
            //转发到一个请求方法(同一个控制器类中可以省略/index/)
            return "forward:/index/isLogin";
        }
    
        @RequestMapping("/isLogin")
        public String isLogin(){
            //重定向到一个请求方法
            return "redirect:/index/isRegister";
        }
        
        @RequestMapping("/isRegister")
        public String isRegister(){
            //转发到一个视图
            return "register";
        }
    }

     在SpringMVC框架中,不管是重定向或转发,都需要符合视图解析器的配置,如果直接转发到一个不需要DispatcherServlet的资源,例如:

    //转发到一个静态资源
    return "forward:/html/my.html";

     则需要在springmvc.xml中配置mvc:resources元素,示例代码:

    <mvc:resources mapping="/html/**" location="/html/"></mvc:resources>

    4、应用@Autowired进行依赖注入

    在Controller类中需要使用org.springframework.beans.factory.annotation.Autowired注解类型将依赖注入到一个属性或方法,例如:

    @Autowired
    private UserService userService;

     在Spring MVC中,为了能被作为依赖注入,类必须使用org.springframework.stereotype.Service注解类型注明为@Service(一个服务)。另外还需要在配置文件中使用<context:component-scan>元素来扫描依赖基础包

    Service类代码如下:

    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        public void login(User user){
            System.out.println(user);
        }
    }

    在springmvc.xml中添加扫描:

    <context:component-scan base-package="com.demo.service"></context:component-scan>

    Controller类代码如下:

    @Controller
    public class TestController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/login")
        public String login(User user){
            userService.login(user);
            return "test";
        }
    
    }

    如果在Controller类中注入属性时出错,例如:

    出现这种问题的四种原因:

    • 如果使用注解配置,service类上可能缺少@Service注解
    • 如果用xml配置,是否写了定义
    • 检查springmvc.xml中扫描包路径是否正确
    • service类中实现的接口是否存在相同方法名的接口

    5、@ModelAttribute注解

    通过org.springframework.web.bind.annotation.ModelAttribute注解类型可以经常实现以下两个功能:

    5.1、绑定请求参数到实体对象

    Controller类代码示例:

    @Controller
    public class TestController {
        @RequestMapping("/login")
        public String login(@ModelAttribute("user") UserForm user) {
            //业务逻辑代码
            return "index";
        }
    }

    上述代码中的形参 @ModelAttribute("user") UserForm user 的功能有两个:

    • 一是将请求参数的输入封装到user对象中
    • 二是创建UserForm实例,以user为键值存储在Model对象中,和 model.addAttribute("user",user) 语句的功能一样。

    如果没有指定键值,即使用 @ModelAttribute UserForm user 为形参,那么在创建UserForm实例时以"userForm"为键值存储在Model对象中,和 model.addAttribute("userForm",user) 语句的功能一样。

    5.2、注解一个非请求处理方法

    被@ModelAttribute注解的方法将在每次调用控制器类的请求处理方法前被调用。这种特性可以用来控制登录权限。
    创建BaseController类,代码如下:

    public class BaseController {
        @ModelAttribute
        public void isLogin(HttpSession session) throws Exception {
            if(session.getAttribute("user") == null){
                throw new Exception("没有权限");
            }
        }
    }

    创建接收请求的Controller类,代码如下:

    @Controller
    @RequestMapping("/admin")
    public class TestController extends BaseController {
        @RequestMapping("/add")
        public String add(){
            return "test";
        }
    }

    在访问 "http://localhost:8080/admin/add" 时,会先执行BaseController类中的isLogin()方法,显示效果如下:

  • 相关阅读:
    8. String to Integer (atoi) Java Solutin
    171. Excel Sheet Column Number Java Solutin
    217. Contains Duplicate Java Solutin
    242. Valid Anagram Java Solutin
    258. Add Digits Java Solutin
    win7刷新图标缓存
    [转]如何编程实现 2 + 2 = 5?
    [转]Java FileInputStream与FileReader的区别
    Excel中连接函数CONCATENATE()
    [转]Web基础架构:负载均衡和LVS
  • 原文地址:https://www.cnblogs.com/jpwz/p/10539893.html
Copyright © 2020-2023  润新知