• 吴裕雄天生自然SPRING基于注解的控制器


    Controller注解类型
    
    在Spring MVC中,使用org.springframework.stereotype.Controller注解类型声明某类的实例是一个控制器。
    RequestMapping注解类型
    
    在基于注解的控制器类中,可以为每个请求编写对应的处理方法。需要使用org.springframework.web.bind.annotation.RequestMapping注解类型将请求与处理方法一一对应。
    
    1.方法级别注解
    @RequestMapping(value = "/index/login")
    public String login() {}
    
    注解的value属性将请求URI映射到方法,value属性是RequestMapping注解的默认属性,如果就一个value属性,则可省略该属性。可以使用如下URL访问login方法(请求处理方法)。
    http://localhost:xxx/yyyy/index/login    
    2 类级别注解
    
    @Controller
    @RequestMapping("/index")
    public class IndexController {
        @RequestMapping("/login")
        public String login() {
            return "login";
        }
        @RequestMapping("/register")
        public String register() {
            return "register";
        }
    }
    
    
    在类级别注解的情况下,控制器类中的所有方法都将映射为类级别的请求。可以使用如下URL访问login方法。
    http://localhost:xxx/yyy/index/login
    编写请求处理方法
    
    1.请求处理方法中常出现的参数类型
        Servlet API、输入输出流、表单实体类、注解类型、Model等Java类型。
    public String login(HttpSession session, HttpServletRequest request) 
    2.请求处理方法常见的返回类型
        最常见的返回类型,就是代表逻辑视图名称的String类型。除了String类型外,还有Model、View以及其他任意的Java类型。
    public String register(Model model) {}
    Controller接收请求参数的常见方式
    
        Controller接收请求参数的方式有很多种,有的适合get请求方式,有的适合post请求方式,有的两者都适合。
        1.通过实体bean接收请求参数
        通过一个实体bean来接收请求参数,适用于get和post提交请求方式。需要注意的是,bean的属性名称必须与请求参数名称相同。
        2.通过处理方法的形参接收请求参数
        通过处理方法的形参接收请求参数,也就是直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求参数名称完全相同。该接收参数方式适用于get和post提交请求方式。
    3.通过@RequestParam接收请求参数
        通过@RequestParam接收请求参数,适用于get和post提交请求方式。通过@RequestParam接收请求参数与“通过处理方法的形参接收请求参数”的区别是:当请求参数与接收参数名不一致时,“通过处理方法的形参接收请求参数”不会报400错误,而“通过@RequestParam接收请求参数”会400错误。
    4.通过@ModelAttribute接收请求参数
        @ModelAttribute注解放在处理方法的形参上时,用于将多个请求参数封装到一个实体对象,从而简化数据绑定流程,而且自动暴露为模型数据用于视图页面展示时使用。而“通过实体bean接收请求参数”只是将多个请求参数封装到一个实体对象,并不能暴露为模型数据(需要使用model.addAttribute语句才能暴露为模型数据)
    重定向与转发
    
    重定向是将用户从当前处理请求定向到另一个视图(如JSP)或处理请求,以前的请求(request)中存放的信息全部失效,并进入一个新的request作用域;
    
    转发是将用户对当前处理的请求转发给另一个视图或处理请求,以前的request中存放的信息不会失效。
    
    转发是服务器行为,重定向是客户端行为。具体工作流程如下:
    转发过程:客户浏览器发送http请求,Web服务器接受此请求,调用内部的一个方法在容器内部完成请求处理和转发动作,将目标资源发送给客户;在这里,转发的路径必须是同一个Web容器下的URL,其不能转向到其他的Web路径上去,中间传递的是自己的容器内的request。在客户浏览器的地址栏中显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
    
    重定向过程:客户浏览器发送http请求,Web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求URL是新的location地址,服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址的变化。重定向行为是浏览器做了至少两次的访问请求。
    
    在Spring MVC框架中,控制器类中处理方法的return语句默认就是转发实现,只不过实现的是转发到视图。
    //转发到一个请求方法(同一个控制器类里,可省略/index/)
    return "forward:/index/isLogin";
    //重定向到一个请求方法
    return "redirect:/index/isRegister";
    //转发到一个视图
    return "register";
    
    在Spring MVC框架中,不管重定向或转发,都需要符合视图解析器的配置,如果直接重定向到一个不需要DispatcherServlet的资源,如:
    return "redirect:/html/my.html";
    在Spring MVC配置文件中,需要使用mvc:resources配置:
    <mvc:resources location="/html/" mapping="/html/**"></mvc:resources>
    在Spring MVC配置类中,需要实现WebMvcConfigurer的接口方法public void addResourceHandlers(ResourceHandlerRegistry registry),示例代码如下:
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/html/**").addResourceLocations("/html/");
        }
    应用@Autowired进行依赖注入
    
        Spring MVC框架本身就是一个非常优秀的MVC框架,它具有一个依赖注入的优点。可以通过org.springframework.beans.factory.annotation.Autowired注解类型将依赖注入到一个属性(成员变量)或方法,如:
    @Autowired
    public UserService userService;
    在Spring MVC中,为了能被作为依赖注入,服务层的类必须使用org.springframework.stereotype.Service注解类型注明为@Service(一个服务)。另外,还需要在配置文件中使用<context:component-scan base-package="基本包"/>元素或者在配置类中使用@ComponentScan("基本包")来扫描依赖基本包。
    
    “登录”和“注册”的业务逻辑处理分离出来,使用Service层实现。
    首先,创建service包,在包中创建UserService接口和UserServiceImpl实现类。
    其次,将配置类中@ComponentScan("controller")修改如下:
    @ComponentScan(basePackages = {"controller","service"})//扫描基本包
    最后,修改控制器类UserController,具体代码如下:
    public class UserController {
        //将服务层依赖注入到属性userService
        @Autowired
         public UserService userService;
    @ModelAttribute
    
        通过org.springframework.web.bind.annotation.ModelAttribute注解类型,可经常实现如下两个功能:
        1.绑定请求参数到实体对象(表单的命令对象)
    public String register(@ModelAttribute("user") UserForm user) {}
        “@ModelAttribute(”user“) UserForm user”语句的功能有两个,一是将请求参数的输入封装到user对象中;一是创建UserForm实例,以“user”为键值存储在Model对象中,与“model.addAttribute(”user“, user)”语句功能一样。如果没有指定键值,即“@ModelAttribute UserForm user”,那么创建UserForm实例时,以“userForm”为键值存储在Model对象中,与“model.addAttribute(”userForm“, user)”语句功能一样。
        2.注解一个非请求处理方法
        被@ModelAttribute注解的控制器的一个非请求处理方法,将在每次调用该控制器类的请求处理方法前被调用。
    表单标签库
    
        表单标签库中包含了可以用在JSP页面中渲染HTML元素的标签。JSP页面使用Spring表单标签库时,必须在JSP页面开头处声明taglib指令,指令代码如下:
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
        表单标签库中有form、input、password、hidden、textarea、checkbox、checkboxes、radiobutton、radiobuttons、select、option、options、errors。
    表单标签
    
        表单标签,语法格式如下:
        <form:form modelAttribute="xxx" method="post" action="xxx">
            ……
        </form:form>
        除了具有HTML表单元素属性外,表单标签还有具有acceptCharset、commandName、cssClass、cssStyle、htmlEscape和modelAttribute等属性。
    
        其中,commandName和modelAttribute属性功能基本一致,属性值绑定一个JavaBean对象。
    input标签
    
        input标签,语法格式如下:
        <form:input path="xxx"/>
        该标签除了cssClass、cssStyle、htmlEscape属性外,还有一个最重要的属性path。path属性将文本框输入值绑定到form backing object的一个属性。
    password标签
    
        password标签,语法格式如下:
        <form:password path="xxx"/>
        该标签与input标签用法完全一致
    hidden标签
    
        hidden标签,语法格式如下:
        <form:hidden path="xxx"/>
        该标签与input标签用法基本一致,只不过它不可显示,不支持cssClass和cssStyle属性。
    textarea标签
    
        textarea基本上就是一个支持多行输入的input元素,语法格式如下:
        <form:textarea path="xxx"/>
       该标签与input标签用法完全一致
    checkbox标签
    
        checkbox标签,语法格式如下:
        <form:checkbox path="xxx" value="xxx"/>
        多个path相同的checkbox标签,它们是一个选项组,允许多选。选项值绑定到一个数组属性。
    
    <form:checkbox path="friends" value="张三"/>张三
    <form:checkbox path="friends" value="李四"/>李四
    <form:checkbox path="friends" value="王五"/>王五
    <form:checkbox path="friends" value="赵六"/>赵六
    上述示例代码中复选框的值绑定到一个字符串数组属性friends(String[] friends)。
    checkboxes标签
    
        checkboxes标签渲染多个复选框,是一个选项组,等价于多个path相同的checkbox标签。它有3个非常重要的属性:items、itemLabel和itemValue。
        items:用于生成input元素的Collection、Map或Array。
        itemLabel:items属性中指定的集合对象的属性,为每个input元素提供label。
        itemValue:items属性中指定的集合对象的属性,为每个input元素提供value。
        checkboxes标签语法格式如下:
        <form:checkboxes items="xxx"  path="xxx"/>
    <form:checkboxes items="${hobbys}"  path="hobby" />
    上述示例代码,是将model属性hobbys的内容(集合元素)渲染为复选框。itemLabel和itemValue缺省情况下,如果集合是数组,复选框的label和value相同;如果是Map集合,复选框的label是Map的值(value),复选框的value是Map的关键字(key)。
    radiobutton标签
    
        radiobutton标签,语法格式如下:
        <form:radiobutton path="xxx" value="xxx"/>
        多个path相同的radiobutton标签,它们是一个选项组,只允许单选。
    radiobuttons标签
    
        radiobuttons标签渲染多个radio,是一个选项组,等价于多个path相同的radiobutton标签。radiobuttons标签,语法格式如下:
        <form:radiobuttons path="xxx" items="xxx"/>
        该标签的itemLabel和itemValue属性与checkboxes标签的itemLabel和itemValue属性完全一样,但只允许单选。
    
    <form:radiobuttons path="xxx" items="xxx"/>
    该标签的itemLabel和itemValue属性与checkboxes标签的itemLabel和itemValue属性完全一样,但只允许单选。
    select标签
    
        select标签的选项可能来自其属性items指定的集合,或者来自一个嵌套的option标签或options标签。语法格式如下:
        <form:select path="xxx" items="xxx" /><form:select path="xxx" items="xxx" >
         <option value="xxx">xxx</option>
        </ form:select><form:select path="xxx">
           <form:options items="xxx"/>
        </form:select>
        该标签的itemLabel和itemValue属性与checkboxes标签的itemLabel和itemValue属性完全一样。
    options标签
    
        options标签生成一个select标签的选项列表。因此,需要与select标签一同使用,具体用法参见select标签。
    errors标签
    
        errors标签渲染一个或者多个span元素,每个span元素包含一个错误消息。它可以用于显示一个特定的错误消息,也可以显示所有错误消息。语法如下:
        <form:errors path="*"/><form:errors path="xxx"/>
        其中,“*”表示显示所有错误消息;“xxx”表示显示由“xxx”指定的特定错误消息。
    package pojo;
    
    public class UserForm {
        private String uname;// 与请求参数名称相同
        private String upass;
        private String reupass;
    
        public String getUname() {
            return uname;
        }
    
        public void setUname(String uname) {
            this.uname = uname;
        }
    
        public String getUpass() {
            return upass;
        }
    
        public void setUpass(String upass) {
            this.upass = upass;
        }
    
        public String getReupass() {
            return reupass;
        }
    
        public void setReupass(String reupass) {
            this.reupass = reupass;
        }
    }
    package interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class MyInteceptor implements HandlerInterceptor {
        /**
         * 重写preHandle方法在请求发生前执行
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("preHandle方法在请求发生前执行");
            return true;
        }
    
        /**
         * 重写postHandle方法在请求完成后执行
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle方法在请求完成后执行");
        }
    }
    package config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.multipart.MultipartResolver;
    import org.springframework.web.multipart.commons.CommonsMultipartResolver;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.view.InternalResourceViewResolver;
    
    import interceptor.MyInteceptor;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = { "controller", "service" })
    public class SpringMVCConfig implements WebMvcConfigurer {
        /**
         * 配置视图解析器
         */
        @Bean
        public InternalResourceViewResolver getViewResolver() {
            InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
            viewResolver.setPrefix("/WEB-INF/jsp/");
            viewResolver.setSuffix(".jsp");
            return viewResolver;
        }
    
        /**
         * 配置静态资源
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/html/**").addResourceLocations("/html/");
            // addResourceHandler指的是对外暴露的访问路径
            // addResourceLocations指的是静态资源存放的位置
        }
    
        /**
         * 配置拦截器Bean
         */
        @Bean
        public MyInteceptor myInteceptor() {
            return new MyInteceptor();
        }
    
        /**
         * 重写addInterceptors方法注册拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(myInteceptor());
        }
    
        /**
         * MultipartResolver配置
         */
        @Bean
        public MultipartResolver multipartResolver() {
            CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
            // 设置上传文件的最大值,单位为字节
            multipartResolver.setMaxUploadSize(5400000);
            // 设置请求的编码格式,默认为iso-8859-1
            multipartResolver.setDefaultEncoding("UTF-8");
            return multipartResolver;
        }
    }
    package config;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration.Dynamic;
    
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
    
    public class WebConfig implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext arg0) throws ServletException {
            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(SpringMVCConfig.class);// 注册Spring MVC的Java配置类SpringMVCConfig
            ctx.setServletContext(arg0);// 和当前ServletContext关联
            /**
             * 注册Spring MVC的DispatcherServlet
             */
            Dynamic servlet = arg0.addServlet("dispatcher", new DispatcherServlet(ctx));
            servlet.addMapping("/");
            servlet.setLoadOnStartup(1);
        }
    }
    package service;
    
    import pojo.UserForm;
    
    public interface UserService {
        boolean login(UserForm user);
        boolean register(UserForm user);
    }
    package service;
    
    import org.springframework.stereotype.Service;
    
    import pojo.UserForm;
    
    //注解为一个服务
    @Service
    public class UserServiceImpl implements UserService {
        @Override
        public boolean login(UserForm user) {
            if ("zhangsan".equals(user.getUname()) && "123456".equals(user.getUpass()))
                return true;
            return false;
        }
    
        @Override
        public boolean register(UserForm user) {
            if ("zhangsan".equals(user.getUname()) && "123456".equals(user.getUpass()))
                return true;
            return false;
        }
    }
    package controller;
    
    import javax.servlet.http.HttpSession;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import pojo.UserForm;
    import service.UserService;
    
    @Controller
    @RequestMapping("/user")
    public class UserController {
        // 得到一个用来记录日志的对象,这样打印信息的时候能够标记打印的是那个类的信息
        private static final Log logger = LogFactory.getLog(UserController.class);
    
        // 将服务层依赖注入到属性userService
        @Autowired
        public UserService userService;
    
        /**
         * 处理登录
         */
        @RequestMapping("/login")
        public String login(UserForm user, HttpSession session, Model model) {
            if (userService.login(user)) {
                session.setAttribute("u", user);
                logger.info("成功");
                return "main";// 登录成功,跳转到main.jsp
            } else {
                logger.info("失败");
                model.addAttribute("messageError", "用户名或密码错误");
                return "login";
            }
        }
    
        /**
         * 处理注册
         */
        @RequestMapping("/register")
        public String register(@ModelAttribute("user") UserForm user) {
            if (userService.register(user)) {
                logger.info("成功");
                return "login";// 注册成功,跳转到login.jsp
            } else {
                logger.info("失败");
                // 使用@ModelAttribute("user")与model.addAttribute("user", user)功能相同
                // 在register.jsp页面上可以使用EL表达式${user.uname}取出ModelAttribute的uname值
                return "register";// 返回register.jsp
            }
        }
    
    }
  • 相关阅读:
    去掉返回数据存在HTML节点问题
    ios8 地图不能定位问题的解决办法
    日期选择器
    定位的系统实现简单方法
    NSMutableString 的使用例子
    UIImagePickerController--------图片选取器
    代码中判断网络类型的类别
    Gitbook Android App
    Ionic 整合 pixi.js
    ionic app调试问题
  • 原文地址:https://www.cnblogs.com/tszr/p/15312210.html
Copyright © 2020-2023  润新知