• springmvc的使用


    springmvc的配置

    1.配置springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- 配置spring创建容器时扫描的包 -->
        <context:component-scan base-package="cn.maoritian"></context:component-scan>
        
        <!-- 配置视图解析器,用于解析项目跳转到的文件的位置 -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
        
        <!-- 配置spring开启注解mvc的支持 -->
        <mvc:annotation-driven></mvc:annotation-driven>
    </beans>

    2.配置springmvc的核心核心控制器DispatcherServlet

    <web-app>
        <!-- 配置核心控制器 -->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 使核心控制器初始化时读取bean.xml文件创建Spring核心容器 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:bean.xml</param-value>
            </init-param>
            <!-- 设置该Servlet的优先级别未最高,使之最早创建 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

    Springmvc的使用

    @Controller
    public class HelloController {
    
        @RequestMapping(path="/hello")    // 指定方法对应的URL
        public String helloHandler() {
            System.out.println("Hello SpringMVC!!");
            return "success";    // 指定跳转的视图的地址,被ViewResolver解析为 /WEB-INF/pages/success.jsp
        }
    }

    案例执行流程分析

    案例的执行流程

    1. 启动Tomcat服务器时,由于配置了<load-on-startup>标签,所以首先创建DispatcherServlet对象并加载bean.xml配置文件
    2. 由于bean.xml中开启了注解扫描,HelloController对象被创建并加入Spring容器中
    3. 浏览器请求index.jsp,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解找到具体要执行的方法helloHandler
    4. 执行方法helloHandler,得到返回值. 的视图解析器解析返回值,查找到对应的JSP文件success.jsp
    5. Tomcat服务器渲染页面,做出响应

    请求路径匹配

    @RequestMappin注解用于建立请求url路径处理器之间的对应关系

    出现位置:可以出现在类上,也可以出现在方法上

      当他出现在类上也出现杂在方法上是,类上注解值为请求URL的一级目录,方法上注解值为请求URL的二级目录

      当它只出现在方法上时,该注解为请求URL的一级目录

    其属性如下:

      path:value属性的别名,指定请求的URL.

      method:指定HTTP请求的方法

      params:指定请求参数的限制,支持简单的表达式如:

      @RequestMapping(params={“param1”}),表示请求参数中param1必须出现

      @RequestMapping(params={‘’!param1'}),表示请求参数中param1不能出现

      @RequestMapping(params={"param1=value1"}),表示请求参数中param1必须出现且为value1

      @RequestMapping(params={"param1!value1"}),表示请求参数中param1必须出现且不为value1

    @PathVariable注解的使用

    <a href="account/findAccount/10">查询账户</a>
    // 控制器类
    @Controller
    @RequestMapping(path = "/account")
    public class HelloController {
    
        @RequestMapping("/findAccount/{id}")
        public void findAccount(@PathVariable(name = "id") Integer accountId) {
            // accountId = 10
            // 方法体...
        }
    }

    访问URLhttp://localhost:8080/myProject/account/findAccount/10会将10传给findAccount方法的accountId参数

    请求参数的绑定

    <a href="account/findAccount?accountId=10">查询账户</a>
    // 控制器类
    @Controller
    @RequestMapping(path = "/account")
    public class HelloController {
    
        @RequestMapping(path = "/findAccount")
        public void findAccount(Integer accountId) {
            // accountId = 10
            // 方法体...
        }
    }

    SpringMVC中会将10传给findAccount方法的accountID参数传递给HandlerAdapter执行.

    @RequestParam注解:微处理器方法参数起别名

    @RequestParam注解作用在方法参数上,把请求中指定名称的参数给处理器方法中的形参赋值

    属性如下:

      name:value属性的别名,指定请求参数的名称

      required:指定该请求参数是否是必须的,默认为true

    <a href="testRequestParam?param1=value">测试requestParam注解</a>

    处理器方法中给对应参数加上@RequestParam(name="param1")注解来接收参数

    @RequestMapping("/testRequestParam")
    public String handlerMethod(@RequestParam("param1") String username) {
        // 方法体...
    }

    各种类型请求参数的绑定

    SpringMVC内置参数绑定类型

      1.SpringMVC支持三种类型的参数绑定

      2.JavaBean类型

      3.集合类型

    数据绑定要求请求参数明和方法中的参数明相同,或使用@RequestParam为方法参数起别名.

    基本数据类型和String类型的参数绑定

    对于基本数据类型,只需要以方法参数名作为请求参数名即可.示例如下:

    <a href="account/findAccount?accountId=10&accountName=zhangsan">查询账户</a>
    // 控制器类
    @Controller
    @RequestMapping(path = "/account")
    public class HelloController {
    
        @RequestMapping("/findAccount")
        public String findAccount(Integer accountId, String accountName) {
            // accountId = 10, accountName = "zhangsan"
            // 方法体...
        }
    }

    JavaBean类型的参数绑定

    JavaBean类型的参数,要想实现绑定,就必须实现其空参构造函数和所有属性的get,set方法

      1.若JavaBean参数的属性中只包含基本数据类型和String类型属性,以属性名作为请求参数名,则SpringMVC会自动将其封装成JavaBean对象.示例如下:

      javaBean类的定义如下

    // JavaBean类
    public class Account implements Serializable {
    
        private String username;
        private Integer age;
    
        // 所有属性的getset方法...
    }

    则其对应的请求参数名如下:

    <form action="account/updateAccount" method="post">
        <label>名称</label><input type="text" name="username"><br/>
        <label>年龄</label><input type="text" name="age"><br/>
        <input type="submit" value="保存">
    </form>

      2.若JavaBean参数的属性中包含其它JavaBean对象,则以外层类属性名.内层类属性名作为请求参数

      

    public class Account implements Serializable {
    
        private String username;
        private Intger age;
        private User user;
    
        // 所有属性的getset方法...
    }
    
    public class User implements Serializable{
    
        private String uname;
        private Double umoney;
        
        // 所有属性的getset方法...
    }

    则其对应的请求参数名如下:

    <form action="account/updateAccount" method="post">
        <label>名称</label><input type="text" name="username"><br/>
        <label>年龄</label><input type="text" name="age"><br/>
        <label>用户名</label><input type="text" name="user.uname"><br/>
        <label>用户余额</label><input type="text" name="user.umoney"><br/>
        <input type="submit" value="保存">
    </form>

    自定义数据类型参数绑定

    表单提交的任何数据类型都是字符串类型,SpringMVC定义了转换器,将字符串转化为我们方法参数的各种类型.我们也可以实现自定义的转换器以实现自定义的参数类型转换
    自定义的类型转换器要实现Converter<String, T>接口,并在Spring容器配置bean.xml中配置该实现类. 示例如下:

    // 自定义的类型转换器,完成从String类到Date类的转换
    public class StringToDateConverter implements Converter<String, Date> {
    
        public Date convert(String source) {
            try {
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                Date date = df.parse(source);
                return date;
            } catch (Exception e) {
                throw new RuntimeException("类型转换错误");
            }
        }
    }
    <!-- 配置的类型转换器工厂 -->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!-- 诸如我们自定义的类型转换器 -->
                <bean class="cn.maoritian.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>

    通过原始ServletAPI对象处理请求

    SpringMVC支持使用原始ServletAPI作为控制器方法的参数,包括HttpServletRequest,HttpServletResponse,HttpSession对象,他们都可以直接用做控制器方法的参数.示例如下:

    @RequestMapping("/path")
    public void myHandler(HttpServletRequest request, HttpServletResponse response) throws IOException {
        
        System.out.println(request.getParameter("param1"));
        System.out.println(request.getParameter("param1"));
    
        response.getWriter().println("<h3>操作成功</h3>");
    
    }

    解决请求参数绑定中文乱码问题

    在web.xml配置编码转换过滤器,即可解决请求参数中文乱码的问题.

    <!-- 配置编码转换过滤器 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filterclass>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!-- 过滤所有请求 -->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    小知识点:/不会匹配到.jsp /*会匹配到.jsp

    通过处理器方法返回值指定返回视图

    SpringMVC中的处理器方法的返回值用来指定页面跳转到哪个视图,处理器的返回值可以为String,void,ModelAndView对象.

    处理器返回String对象:转发到字符串指定的URL

    处理器方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址.

    在本例中,因为我们在Spring容器配置文件bean.xml中配置的视图解析器中注入prefixsuffix属性,所以视图解析器会把处理器返回的"字符串值"解析为"/WEB-INF/pages/字符串值.jsp",再请求对应视图.这是一个请求转发过程,浏览器地址栏不会发生变化.

    bean.xml中配置的视图解析器如下:

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    处理器方法如下:

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/testString")
        public String testString(Model model) {
            // 执行方法体...向隐式对象添加属性attribute_user,可以在jsp中通过 ${attribute_user} 获取到
            model.addAttribute("attribute_user", new User("张三", "123"));
            
            // 经过视图解析器的处理,SpringMVC会将请求转发到/WEB-INF/pages/succeess.jsp,但浏览器地址栏显示的一直是 项目域名/user/testString
            return "success";
        }
    }

    处理器返回void:转发到当前URL

    处理器返回ModelAndView对象:更灵活地添加属性和指定返回视图

    ModelAndView为我们提供了一种更灵活地为页面添加属性和指定返回视图的方法,其主要方法如下:

    1.public ModelMap getModelMap():返回当前页面的ModelMap对象.

    2.public ModelAndView addObject(Object attributeValue): 向当前页面的ModelMap对象中添加属性

    3.public void setViewName(@Nullable String viewName): 指定返回视图,viewName会先被视图解析器处理解析成对应视图.

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/testModelAndView")
        public ModelAndView testModelAndView() {
            
            // 创建ModelAndView对象
            ModelAndView mv = new ModelAndView();
            
            // 向model中存入属性attribute_user
            mv.addObject("attribute_user", new User("张三", "123"));
    
            // 指定返回视图,视图解析器将"success"解析为视图URL /WEB-INF/pages/succeess.jsp
            mv.setViewName("success");
    
            return mv;
        }
    }

    使用SpringMVC框架提供的请求转发

    要使用SpringMVC框架提供的请求转发,只需要在处理器方法返回的viewName字符串首加上forward:即可,要注意的是,此时forward:后的地址不能直接被视图解析器解析,因此要写完整的相对路径.示例如下:

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/testForward")
        public String testForward() {
            // 在forward:要写完整的相对路径
            // return "forward:success"    // 错误,会将请求转发到 /项目名/user/success
            return "forward:/WEB-INF/pages/success.jsp";
        }
    }

    使用SpringMVC框架提供的重定向

    要使用SpringMVC框架提供的请求重定向,只需要在处理器方法返回的viewName字符串首加上redirect:即可,要注意的是,此时redirect:后的地址要写相对于ContextPath的地址.示例如下:

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/testRedirct")
        public String testRedirct() {
            // 在forward:要写完整的相对路径
            // return "redirect:" + request.getContextPath() + "/index.jsp";    // 错误,会将请求转发到 /项目名/项目名/index.jsp
            return "redirect:/index.jsp";
        }
    }

    SpringMVC响应json数据

    前期准备

     1.jsp在页面上引入jQuery以发送json数据,因此需要向服务器发起一个对jQuery的请求.像这种对静态资源的请求,不应当经过具体的某个处理器处理,而应当直接返回对应的静态资源.

      因此我们需要在Spring容器配置bean.xml中使用<mvc:resources>标签声明该资源为静态资源,否则请求该资源会报404错误.该标签的属性如下:

      1.location属性;表示该资源在服务器上所在的位置,必须是一个有效的目录

      2.mapping属性:指定匹配的URL

      我们在bean.xml中配置各静态文件的位置如下.

    在jsp中编写代码发送json数据

    在jsp页面中编写代码发送json请求如下:

    <script>
    // 页面加载,绑定单击事件
    $(function () {
        $("#btn").click(function () {
            // 发送ajax请求
            $.ajax({
                // 配置请求参数
                url: "user/testAjax",
                contentType: "application/json;charset=UTF-8",
                dataType: "json",
                type: "post",
                // 请求的json数据
                data: '{"username":"myname","password":"mypassowrd","age":30}',
                // 回调函数,处理服务器返回的数据returnData
                success: function (returnData) {
                    // 我们假定服务器返回的是一个user对象,将其输出在控制台上
                    console.log(returnData);            }
            });
        });
    });
    </script>

    在控制器中编写代码响应json数据

    使用@RequestBody注解将请求绑定到控制器方法参数上,使用@ResponseBody注解表示将该方法的返回值直接写回到HTTP响应中,而不会存入Model解析为视图名

    @RequestBody会将json对象封装为对应的javaBean对象

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/testAjax")
        @ResponseBody
        public User testAjax(@RequestBody User user) {
    
            System.out.println(user);
            
            // 将user对象返回给前端页面
            return user;
        }
    }

     异常处理器

    当程序发生错误时,错误最终会传递给DispatcherServlet,由DispatcherServlet进行异常处理.

    1.创建自定义异常类

    package cn.maoritian.exception;
    
    public class SysException extends Exception {
    
        // 存储提示信息的
        private String message;
    
        // 构造方法
        public SysException(String message) {this.message = message; }
    
        // get,set方法
        public String getMessage() {return message; }
        public void setMessage(String message) {this.message = message; }
    }

    2.创建异常处理器,异常处理器必须实现HandlerExceptionResolver接口,其resolveException()方法执行异常处理.

    package cn.maoritian.exception;
    
    // 自定义异常处理器
    public class MyExceptionResolver implements HandlerExceptionResolver {
    
        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    
            myException e = null;
            if (ex instanceof myException) {
                e = (myException) ex;
            } else {
                e = new myException("其他错误");
            }
            
            ModelAndView mv = new ModelAndView();
            mv.addObject("errorMsg", e.getMessage());   // 封装错误信息
            mv.setViewName("error");                    // 跳转页面
            return mv;
        }
    }

    3.向spring容器中注入异常处理器

    <!--配置异常处理器-->
    <bean id="myExceptionResolver" class="cn.maoritian.exception.MyExceptionResolver"/>

    拦截器

    SpringMVC中的拦截器只能拦截controller中的方法.

    1.自定义拦截器需要继承HandlerInterceptor接口,该接口定义了三个方法,都有其默认实现:

      1.preHandle(...):该方法在处理器方法执行之前执行

      2.postHandle(...):该方法在处理器方法实际执行完毕以后执行

      3.afterCompletion(...):该方法在整个请求处理完成后执行

      其中preHandle(..)方法返回一个boolean值,可以通过这个方法来决定是否继续执行处理链中的部件。当方法返回 true时,处理器链会继续执行;若方法返回 false, DispatcherServlet即认为拦截器自身已经完成了对请求的处理(比如说,已经渲染了一个合适的视图),那么其余的拦截器以及执行链中的其他处理器就不会再被执行了。

    public class MyIntercepter implements HandlerInterceptor{
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            System.out.println("过滤器执行成功");
            return true;
        }

    2.向Spring容器中注入拦截器

    <mvc:interceptors>
    
        <mvc:interceptor>
            <!-- 拦截的方法 -->
            <mvc:mapping path="/**" />
            <!-- 具体的拦截器 -->
            <bean id="officeHoursInterceptor" class="cn.maoritian.interceptor.TimeBasedAccessInterceptor">
                <property name="openingTime" value="9"/>
                <property name="closingTime" value="18"/>
            </bean>
        </mvc:interceptor>
    
    </mvc:interceptors>
  • 相关阅读:
    4 stackstorm定时器基础 Sky
    3 stackstorm rule Sky
    2 stackstrom action Sky
    1 StackStorm介绍 Sky
    stackstorm安装 Sky
    stackstorm webui安装 Sky
    3.8 Go之并发和并行
    3.2 Go之语言竞争状态
    3.2 Go之语言并发通信
    图床_typora设置.md
  • 原文地址:https://www.cnblogs.com/lzh66/p/13558991.html
Copyright © 2020-2023  润新知