SpringMVC学习二

1、控制器方法的返回值类型

(1)返回的是字符串类型:用返回的字符串和配置的视图解析器一起,跳转到指定的页面;
(2)没有返回值(void):可以用原生的Servlet的请求转发或重定向到其他页面;
(3)返回值是ModelAndView类型,,用setViewName方法指定跳转页面!!
测试:
springmvc.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="cn.melo"></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>

    <!--开启支持springmvc注解支持-->
    <mvc:annotation-driven/>
</beans>

index.jsp:
在这里插入图片描述
控制器类:
PersonController.java:

package cn.melo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author hejm
 * @date 2019/11/20
 */
@Controller
@RequestMapping(path = "/person")
public class PersonController {

    @RequestMapping(path = "/test1")
    public String test1(){
        System.out.println("返回值是字符串!!");
        return "success";
    }

    @RequestMapping(path = "/test2")
    public void test2(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("返回值是void!!");
        request.getRequestDispatcher("/hello.jsp").forward(request,response);
    }

    @RequestMapping(path = "/test3")
    public ModelAndView test3(ModelAndView mav){
        //指定跳转路径
        mav.setViewName("success");

        //添加携带的对象
        mav.addObject("xx","XX");
        return mav;
    }
}

页面结构:
在这里插入图片描述
测试结果:
都能跳转成功,而且还可以用${requestScope.xx}取出ModelAndView中存储的对象!

2、springMVC提供的请求转发和请求重定向

如果控制器方法的返回值是字符串,可以在字符串前面加上"forward:"(表示请求转发)或者是"redirect:"(表示请求重定向)!
当然也可以用servlet的原始api搞定!

3、DispatcherServlet拦截静态资源的问题

DispatcherServlet会拦截所有资源,导致一些静态资源(img,js,css)也会被拦截,从而不能使用,解决这个问题就是在springmvc.xml中配置<mvc:resources>即可:
在这里插入图片描述
location表示webapp目录下的所有文件;
mapping表示以/static开头的所有请求路径!

4、@RequestBody和@ResponseBody

(1)@RequestBody可以写在处理器方法的形参前面,可以获取请求体数据
(2)@ResponseBody写在控制器方法上(或者方法的返回值前面),可以把JavaBean转化成json直接响应,要求方法的返回值类型是JavaBean,且要引入jackson的核心包和依赖包;

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.0</version>
    </dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.10.0</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.10.0</version>
</dependency>

测试:
实体类:
person.java:

package cn.melo.bean;

/**
 * @author hejm
 * @date 2019/11/20
 */
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.4.1.js"></script>
    <script type="text/javascript">
        $(function() {
            $("#bt1").click(function () {
                $.ajax({
                    url: "person/testJson",
                    type: "POST",
                    dataType: "JSON",
                    success: function(data){
                        alert(data.name + "------" +data.age);
                        alert(JSON.stringify(data)); //将json对象转换成字符串)
                    },
                    sync: true
                });
            });
        });
    </script>
</head>
<body>
    <button id="bt1">点击获取json数据</button>
</body>
</html>

控制器类中的方法:

@RequestMapping(path = "/testJson")
@ResponseBody
public Person testJson(){
    Person person = new Person("melo",18);
    return person;
}

结果:
在这里插入图片描述
在这里插入图片描述

5、springMVC文件上传问题:

(1)步骤:
A、引入fileupload和io包:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

(2)写上传页面,要求提交方式必须是post,enctype属性为:“multipart/form-data”

<form action="person/fileupload" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="name">
    文件:<input type="file" name="file">
    <input type="submit" value="提交">
</form>

(3)Controller编写:springMVC提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须与表单中type的值是file的标签的name属性值相同:

@RequestMapping(path = "/fileupload")
public String fileupload(MultipartFile file,String name) throws IOException {
    System.out.println("name:"+name);
    String fileName = file.getOriginalFilename();
    System.out.println("fileName:"+fileName);//得到文件名称
    String uuid = UUID.randomUUID().toString().replaceAll("-","")
            .toUpperCase();
    String newFileName = uuid + "_" + fileName;  //给文件取一个新名字
    File f = new File("E:/"+newFileName);//保存图片
    file.transferTo(f);
    return "success";
}

(4)在springmvc.xml中配置文件解析器对象,要求这个bean的id必须是multipartResolver:

<!--配置文件解析器对象,要求id值必须是multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--上传文件的最大大小是5M 单位是bytes -->
    <property name="maxUploadSize" value="5242880"></property>
</bean>

ok,测试结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、springMVC文跨服务器方式上传文件

(1)搭建两个服务器,当然要改掉其中一个的端口号;
在这里插入图片描述
(2)有两个项目,每个项目对应一个服务器!
首先Tomcat默认情况下是只读的,所以要去tomcat的目录下的conf文件夹下找到web.xml文件,在servlet-name是default的那个下面添加一个配制:

<init-param>
   <param-name>readonly</param-name>
   <param-value>false</param-value>
</init-param>

在这里插入图片描述
还要创建文件上传表单和在springmvc.xml中创建文件解析器对象,和上面文件上传是一样的!
除了文件上传需要的io和fileupload的包之外,还要导入两个jersey的jar包:

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-core</artifactId>
  <version>1.19.4</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>1.19.4</version>
</dependency>

控制器类:

@RequestMapping("/fileupload")
public String fileupload(MultipartFile file) throws IOException {
    //获取文件名
    String fileName = file.getOriginalFilename();
    String uuid = UUID.randomUUID().toString().replaceAll("-","")
            .toUpperCase();
    //给文件取新名字
    String newFileName = uuid + "_" + fileName;
    //把文件放到另一个项目(fileupload)的upload这个目录下面
    String path = "http://localhost:9090/fileupload/upload/";

    //创建客户端对象
    Client client = Client.create();

    //连接另一个服务器
    WebResource resource = client.resource(path+newFileName);

    //上传文件
    String s = resource.put(String.class,file.getBytes());

    System.out.println(s);

    System.out.println("跨服务器图片上传成功!!");


    return "success";
}

在fileupload项目的target/fileupload目录创建一个文件夹叫upload!
测试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7、springMVC的异常处理

(1)Controller调用Service,Service调用dao,异常都是向上抛的,最终会由DispatcherServlet找异常处理器对异常进行处理!
(2)自定义异常处理的步骤:
A、创建一个异常类:UserException.java

package cn.melo.exception;

/**
 * @author hejm
 * @date 2019/11/21
 */
public class UserException extends Exception {

    private String message;

    public UserException(String message){
        this.message = message;
    }

    public String getMessage(){
        return this.message;
    }
}

B、定义一个异常处理类实现HandlerExceptionResolver接口,重写resolveException方法;

package cn.melo.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author hejm
 * @date 2019/11/21
 */
public class MyExceptionReolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("error",e.getMessage());
        return modelAndView;
    }
}

C、写异常页面:error.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1 style="color: red">出错啦!!!</h1>
    <h3>${requestScope.error}</h3>
</body>
</html>

D、在springmvc.xml中配置异常处理器类!

<!--配置自定义异常处理器类-->
<bean id="myExceptionReolver" class="cn.melo.exception.MyExceptionReolver"></bean>

测试:
页面:
在这里插入图片描述
Controller类:

@RequestMapping(path = "/testException/{id}")
public String testException(@PathVariable(value = "id") String id) throws UserException {
    if(id.equals("7")) {
        throw new UserException("用户异常!!");
    }
    return "success";
}

测试结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、springMVC中的拦截器

(1)拦截器和过滤器的功能比较相似,区别在于:
A、过滤器是Servlet规范的一部分,任何框架都可以用过滤器技术;
拦截器是springMVC独有的
C、过滤器配置了/*以后可以拦截任何资源
拦截器只会拦截控制器类中的控制器方法!

拦截器也是一种AOP思想的体现!
(2)自定义拦截器步骤:
A、创建类,实现HandlerInterceptor接口,重写preHandle方法,return true表示放行,return false表示拦截!

package cn.melo.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author hejm
 * @date 2019/11/21
 */
public class MyInterceptor implements HandlerInterceptor {
    @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		System.out.println("被拦截了!!!");
        return false;
    }
}

B、在spingmvc.xml中配置拦截器:

<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--拦截的路径-->
        <mvc:mapping path="/testInterceptor/7"/>
        <!--表示不拦截的路径-->
        <mvc:exclude-mapping path="/testInterceptor/1"/>
        <bean id="myInterceptor" class="cn.melo.interceptor.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

C、Controller:

@RequestMapping(path = "/testInterceptor/{id}")
public String testInterceptor(@PathVariable(value = "id") String id){
    System.out.println(id);
    return "success";
}

测试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)HandlerInterceptor中的方法:
A、preHandle:在控制器方法执行前执行:
可以用request跳转到指定页面;
return true;表示放行,如果还有拦截器就执行下一个拦截器,否则就执行要访问的控制器方法!
return falese;表示拦截此次请求,不会执行控制器方法!
B、postHandle:是在控制器方法执行之后,在视图执行之前执行的
可以用request或者response跳转页面,如果跳转了页面,那么控制器方法返回的页面就不会显示!
C、afterCompletion:在视图执行完之后执行,可以在该方法中进行一些资源清理的操作。不能再用request或者response跳转页面!

注意:如果配置了多个拦截器,会按照配置的顺序执行拦截器!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值