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>
原文地址:https://www.cnblogs.com/lzh66/p/13558991.html