自学内容网 自学内容网

SpringMVC介绍及详细使用

介绍

了解SpringMVC之前我们先要了解什么是三层架构
三层架构
1.开发服务器端程序,一般都基于两种形式,一种C/S架构程序,一种B/S架构程序
2.使用Java语言基本上都是开发B/S架构的程序,B/S架构又分成了三层架构
3.三层架构

 表现层:WEB层,用来和客户端进行数据交互的。表现层一般会采用MVC的设计模型
 业务层:处理公司具体的业务逻辑的
 持久层:用来操作数据库的

MVC(Model-View-Controller)是一种常见的软件设计模式,用于将应用程序的逻辑分离成三个独立的组件:
Model:数据模型,JavaBean的类,用来进行数据封装。
View:指JSP、HTML用来展示数据给用户
Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等

Spring Web MVC是基于Servlet API构建的原始Web框架,也是Spring框架的一部分。它提供了灵活可扩展的MVC架构,方便开发者构建高性能的Web应用程序,并与 Spring 生态系统无缝集成。

SpringMVC的入门程序

执行流程

在这里插入图片描述

入门程序

打开idea创建一个mavenWEB项目,在pom文件中导入依赖

<!--  版本锁定  -->
<properties>
  <spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

编写index.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<%--超链接--%>
​
<h3>入门</h3><a href="/hello.do" >入门程序</a>
</body>
</html>

编写Controller类和方法

/**
 * 表现层的类  交给spring去管理
 */
@Controller
//@RequestMapping("/hello")  //第一层路径
public class HelloController {

    @RequestMapping("/hello.do")   //第二层路径
    public String sayHello(){
        System.out.println("SpringMVC入门程序!!");
        return "suc";
    }
}

创建一个springMVC.xml配置文件

<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="com.qcby.controller"/>
    <!--  配置视图解析器  -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

在WEB-INF下面放置一个pages包,创建一个suc.jsp,这就是成功页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功页面</title>
</head>
<body>
<h1>SpringMVC入门案例成功了!!</h1>
</body>
</html>

配置核心的控制器(配置DispatcherServlet)
在web.xml配置文件中核心控制器DispatcherServle

<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 总的Servlet -->
<servlet>
  <servlet-name>dispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!-- 加载springmvc.xml配置文件,配置的是Spring配置 -->
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:SpringMVC.xml</param-value>
  </init-param>
  <!-- 配置启动加载 -->
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>dispatcherServlet</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

之后直接打开就可以了
流程如下:启动tomcat后找到web.xml,就可以加载入SpringMVC.xml的配置文件,配置文件中可以加载视图解析器和找到要管理的类,通过web.xml中的拦截器找到*.do就可以找到方法,调用方法返回字符串suc,最后通过视图解析器找到WEB-INF/pages中的suc.jsp,启动界面
执行流程

RequestMapping注解

在上面的controller中用到了RequestMapping注解,
RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系,通过该注解才能使前端发起请求时找到后端中对应的方法。

RequestMapping注解可以作用在方法和类上
1.作用在类上:第一级的访问目录
2.作用在方法上:第二级的访问目录
3.细节:路径可以不编写 / 表示应用的根目录开始
RequestMapping的属性
1.path 指定请求路径的url
2.value value属性和path属性是一样的,但不可以省略
3.mthod 指定该方法的请求方式
4.params 指定限制请求参数的条件
例如:

 @RequestMapping(path = "/save.do",method = {RequestMethod.GET},params = "username")

请求参数的绑定

SpringMVC 简单的一个或者两个直接可以传递的用参数就可以接收,但是要保证参数名和表单里的input标签的name属性一样
底层通过反射获取到参数进行对比,一旦匹配了就可以接收到
配置文件:

<context:component-scan base-package="com.qcby"/>
<!--  配置视图解析器  -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/>
    <property name="suffix" value=".jsp"/>
</bean>

基本类型数据

Controller类中接收数据

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save.do")
    public String save(String username,Integer age){
        System.out.println("名字:"+username);
        return "suc";
    }
}

jsp页面中表单提交数据

<head>
    <title>演示请求参数的绑定</title>
</head>
<body>
   <h3>SpringMVC请求参数的绑定</h3>
   <form method="post" action="/user/save.do">
       姓名:<input type="text" name="username">
       年龄:<input type="text" name="age">
       <input type="submit" value="提交" />
   </form>
</body>

引用类型和集合数据类型

加上了引用数据类型和list集合和map集合
前端:

</form>
<h3>SpringMVC请求参数的绑定(实体类中由引用类型和集合的绑定)</h3>
<form method="post" action="/user/save3.do">
    姓名:<input type="text" name="username">
    年龄:<input type="text" name="age">
    工资:<input type="text" name="address.money">
    工资1:<input type="text" name="list[0].money">
    工资2:<input type="text" name="map['aaa'].money">
    <input type="submit" value="提交" />
</form>

实体类:

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/save3.do")
    public String save3(User user){
        System.out.println(user);
        return "suc";
    }
}
public class Address {
    private Double money;
    public Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Address{" +
                "money=" + money +
                '}';
    }
}
public class User {
    private String username;
    private Integer age;
    private Address address;
    private List<Address> list;
    private Map<String,Address> map;
    public String getName() {
        return username;
    }
    public Map<String, Address> getMap() {
    return map;
}
    public void setName(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Address> getList() {
        return list;
    }

    public void setList(List<Address> list) {
        this.list = list;
    }

@Override
public String toString() {
    return "User{" +
            "username='" + username + '\'' +
            ", age=" + age +
            ", address=" + address +
            ", list=" + list +
            ", map=" + map +
            '}';
}
}

如果出现中文乱码问题
可以在配置文件中添加

<!-- 配置过滤器,解决中文乱码的问题 -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

日期类型数据

使用日期时xxxx/xx/xx这种形式是可以绑定的,但是实际中xxxx-xx-xx这种形式更多,因此要用别的方法来获取绑定
一、使用DateTimeFormat注解的方式
在类型中的变量前加上注解,pattern为数据按什么格式返回

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;

再在配置文件中加上

<mvc:annotation-driven>

二、自定义类型转换器

import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 *  
 * 自定义类型转换器 把String转换成Date
 */
public class StringToDate implements Converter<String,Date>{
    /**
     * 进行类型转换的方法
     * @param s     用户输入的内容
     * @return
     */
    @Override
    public Date convert(String s) {
        // 判断
        if(s == null){
            throw new RuntimeException("请输入内容");
        }
        // 进行转换
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            // 进行转换
            return sdf.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

注册自定义类型转换器,在springmvc.xml配置文件中编写配置

<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="com.qcby"/>
    <!--  配置视图解析器  -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--配置日期类型转换器,类型转换器的组件,把日期类型转换注入到组件对象中-->
     <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.qcby.demo2.StringToDate" />
            </set>
        </property>
    </bean>
    <!--让映射器、适配器和处理器生效(默认不配置也是可以的)-->
    <mvc:annotation-driven conversion-service="conversionService"/>
</beans>

常用的注解

  1. RequestParam注解

作用:把请求中的指定名称的参数传递给控制器中的形参赋值
属性
a.value:请求参数中的名称
b.required:请求参数中是否必须提供此参数,默认值是true,必须提供,不想传递可以false
c.defaultValue:设置默认值

  1. RequestBody注解

作用:用于获取请求体的内容(注意:get方法不可以)
属性:required:是否必须有请求体,默认值是true

    @RequestMapping("/save2.do")
    public String save2(@RequestBody String body){
        System.out.println("请求体内容:"+body);
        return "suc";
    }
  1. PathVaribale注解
    作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
    属性:value:指定url中的占位符名称
    Restful风格的URL
    1.请求路径一样,可以根据不同的请求方式去执行后台的不同方法
    2.restful风格的URL优点
    a.结构清晰
    b.符合标准
    c.易于理解
    d.扩展方便
    在这里插入图片描述
@Controller
// @RequestMapping("/emp")
public class EmpController {
    @RequestMapping(path = "/emp",method = RequestMethod.POST)
    public String save(){
        System.out.println("保存员工...");
        return "suc";
    }
    @RequestMapping(path = "/emp",method = RequestMethod.GET)
    public String findAll(){
        System.out.println("查询员工...");
        return "suc";
    }
    @RequestMapping(path = "/emp/{id}",method = RequestMethod.GET)
    public String findById(@PathVariable(value = "id") Integer id){
        System.out.println("通过id查询员工..."+id);
        return "suc";
    }
}

修改配置文件

 <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  1. RequestHeader注解

作用:获取指定请求头的值
属性:value:请求头的名称

@RequestMapping("/save3.do")
public String save3(@RequestHeader(value = "Accept") String header){
    System.out.println("Accept请求头的值:"+header);
    return "suc";
}
  1. CookieValue注解

作用:用于获取指定cookie的名称的值
属性:value:cookie的名称

@RequestMapping("/save4.do")
public String save4(@CookieValue(value = "JSESSIONID") String cookie){
    System.out.println("值:"+cookie);
    return "suc";
}

响应数据和结果视图

返回值分类

导入依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${spring.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>${spring.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>${spring.version}</version>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.5</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.servlet.jsp</groupId>
  <artifactId>jsp-api</artifactId>
  <version>2.0</version>
  <scope>provided</scope>
</dependency>

前端控制器和过滤器web.xml

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--过滤器-->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!--总的Servlet-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--加载springmvc.xml配置文件,配置的是Spring配置-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:SpringMVC.xml</param-value>
    </init-param>
    <!--配置启动加载-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

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="com.qcby"/>

    <!-- 设置静态资源不过滤 -->
    <!--<mvc:resources location="/css/" mapping="/css/**"/>  &lt;!&ndash; 样式 &ndash;&gt;-->
    <!--<mvc:resources location="/images/" mapping="/images/**"/>  &lt;!&ndash; 图片 &ndash;&gt;-->
    <!--<mvc:resources location="/js/" mapping="/js/**"/>  &lt;!&ndash; javascript &ndash;&gt;-->

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

    <!--配置文件上传的组件 id名称固定 multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
        <property name="maxUploadSize" value="8388608"/>
    </bean>
    <!--让映射器、适配器和处理器生效-->
    <mvc:annotation-driven/>
</beans>

Controller方法返回各种类型:

@Controller
//@RestController  //使该控制器下的所有的方法的返回都是json形式返回
public class UserController {
    /**
     * 返回String类型
     * @return
     */
    @RequestMapping("/save.do")
    public String save(){
        System.out.println("返回String的形式!!!");
        return "suc";
    }
    /**
     * 返回void类型  没有返回值
     * /WEB-INF/pages/save1.jsp  请求路径的jsp页面
     * @return
     */
    @RequestMapping("/save1.do")
    public void save1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("返回void的形式!!!");
        //request.getRequestDispatcher("/pages/suc.jsp").forward(request,response);
        response.getWriter().print("hello");
    }
    /**
     * 返回ModelAndView  对象形式
     * @return
     */
    @RequestMapping("/save2.do")
    public ModelAndView save2(){
        System.out.println("返回ModelAndView的形式!!!");
        // 创建mv对象
        ModelAndView mv=new ModelAndView();
        // 设置逻辑视图的名称
        mv.setViewName("suc");
        // 把一些数据,存储到mv对象中
        mv.addObject("msg", "用户名或者密码已经存在");
        return mv;
    }
    /**
     * 返回ModelAndView  对象形式
     * @return
     */
    @RequestMapping("/save3.do")
    public String save3(Model model){
        System.out.println("返回ModelAndView的第二种形式!!!");
        // 创建mv对象
        // 设置逻辑视图的名称
        // 把一些数据,存储到mv对象中
        model.addAttribute("msg", "用户名或者密码已经存在00002");
        return "suc";
    }

SpringMVC框架提供的转发和重定向

forward请求转发
controller方法返回String类型,想进行请求转发也可以编写成

@RequestMapping("/save4.do")
public String save4(){
    System.out.println("请求转发执行了...");
    return "forward:/pages/suc.jsp";
}

redirect重定向
controller方法返回String类型,想进行重定向也可以编写成

@RequestMapping("/save5.do")
public String save5(){
    System.out.println("重定向执行了...");
    return "redirect:/pages/suc.jsp";
}

以上方法的前端界面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>响应结果和视图的形式</title>
</head>
<body>
   <H1>返回String的形式!!</H1>
   <a href="/save.do">返回String的形式!</a>
   <H1>返回void的形式!!</H1>
   <a href="/save1.do">返回Viod的形式!</a>
   <H1>返回ModelAndView的形式!!</H1>
   <a href="/save2.do">返回ModelAndView的形式!</a>
   <H1>返回ModelAndView的第二种形式!!</H1>
   <a href="/save3.do">返回ModelAndView的形式!</a>
   <H1>springMVC请求转发</H1>
   <a href="/save4.do">springMVC中的请求转发形式!</a>
   <H1>springMVC重定向</H1>
   <a href="/save5.do">springMVC中的重定向形式!</a>
</body>
</html>

ResponseBody响应json数据

json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包

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

DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
标签配置不过滤
1.location元素表示webapp目录下的包下的所有文件
2.mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b

<!-- 设置静态资源不过滤 -->    
<mvc:resources location="/css/" mapping="/css/**"/>  <!-- 样式 -->    
<mvc:resources location="/images/" mapping="/images/**"/>  <!-- 图片 -->    
<mvc:resources location="/js/" mapping="/js/**"/>  <!-- javascript -->

jsp代码编写

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>发送AJAX异步请求</title>
    <script src="../js/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        //页面加载
        $(function () {
            //单击事件
            $("#btn").click(function () {
               //编写发送ajax的异步请求 传递json数据  返回json数据
                $.ajax({
                    //异步请求路径
                    url:"/save6.do",
                    //请求方式
                    type:"post",
                    //传递的数据类型及编码
                    contentType:"application/json;charset=UTF-8",
                    //传递的参数
                    data:'{"username":"haha","age":"20"}',
                    //回调返回的数据类型  必须是json
                    dataType: "json",
                    //回调函数
                    success:function(d){
                       //处理我们拿到的服务器返回的数据
                       // 编写很多代码
                        alert(d.username+" - "+d.age);
                    }
                })
            })
        })
    </script>
</head>
<body>
  <h1>发送AJAX异步请求 传递JSON数据给服务端  服务端响应JSON数据给前端</h1>
  <input type="button" id="btn" value="ajax交互">
</body>
</html>

后台代码编写

@RequestMapping("/save6.do")
@ResponseBody
public /*@ResponseBody*/ User save6(@RequestBody User user){
    System.out.println("接收json数据返回json数据的方法执行了...");
    System.out.println("前端传递的json串通过注解转变成了对象:"+user);
    user.setAge(28);
    user.setUsername("张三");
    //Object json = JSONObject.toJSON(user1);
    return user;
}
public class User {
    private String username;
    private Integer age;
    public User() {
    }
    public User(String username, Integer age) {
        this.username = username;
        this.age = age;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

文件上传

导入依赖

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.0</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.0</version>
  </dependency>
-------重点是下面两个jar包---------
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
</dependencies>

编写一个界面

<html>
<head>
    <title>springMVC文件上传</title>
</head>
<body>
<h3>文件上传</h3>
<form action="/fileupload.do" method="post" enctype="multipart/form-data">表单中记得写enctype="multipart/form-data"
    选择文件:<input type="file" name="upload" /><br/>
    <input type="submit" value="上传" />
</form>
</body>
</html>

配置文件解析器

<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="com.qcby"/>
    <!--  配置视图解析器  -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--配置文件上传的解析器组件。id的名称是固定,不能乱写-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置上传文件的总大小 8M = 8 * 1024 * 1024 -->
        <property name="maxUploadSize" value="8388608" />
    </bean>
    <!--让映射器、适配器和处理器生效(默认不配置也是可以的)-->
    <mvc:annotation-driven />
</beans>

实现类

@Controller
public class UploadController {

    @RequestMapping("/fileupload.do")
    public String upload(MultipartFile upload, HttpServletRequest request)throws IOException {
        //1. 文件上传的位置 http://127.0.0.1/项目名称/文件夹/01.jpg
        String realPath = request.getSession().getServletContext().getRealPath("/uploads");
        File file= new File(realPath);
        if(!file.exists()){
            file.mkdirs();
        }
        //2.文件名称需不需要处理 每一次上传生成一个唯一的文件名
        //获取文件名
        String filename = upload.getOriginalFilename();
        // 把文件的名称修改成为一的值 sdfs-csdf-fwer-sdfw
        String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        // 直接字符串拼接,产生唯一的值
        filename = uuid+"_"+filename;
        System.out.println("文件名称:"+filename);
        //3.文件上传 file=uploads filename=sdfscsdffwersdfw.jpg
        upload.transferTo(new File(file,filename));
        return "suc";
    }
}

上传好的文件会在target文件夹中
异常处理
异常处理思路:Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进行异常的处理。
编写类模拟异常

@Controller
@RequestMapping("/role")
public class RoleController {
    /**
     * 模拟异常
     * @return
     */
    @RequestMapping("findAll.do")
    public String findAll(){
        System.out.println("controller方法执行了");
        int i =10/0;
        return "suc";
    }
}

自定义异常类

public class MyException extends Exception{
    private String message;
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public MyException(String message) {
        this.message = message;
    }
}

自定义异常处理类

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SysExceptionResolver implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
        e.printStackTrace();
        //做强转
        MyException exception = null;
        // 判断
        if(e instanceof MyException){
            exception=(MyException)e;
        }else {
            exception = new MyException("系统正在维护,请联系管理员");
        }
        // 存入异常提示信息
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        // 设置跳转的页面
        mv.setViewName("error");
        return mv;
    }
}

配置异常处理器

<bean id="sysExceptionResolver" class="com.qcby.controller.SysExceptionResolver" />

jsp错误页面代码

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>错误提示页面</title>
</head>
<body>
<h3>错误的友好提示页面</h3>
${errorMsg}
</body>
</html>

SpringMVC的拦截器

拦截器的概述

SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
拦截器和过滤器的功能比较类似,有区别:
a.过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
b.拦截器是SpringMVC框架独有的。
c.过滤器配置了/*,可以拦截任何资源。
d.拦截器只会对控制器中的方法进行拦截。
拦截器也是AOP思想的一种实现方式
想要自定义拦截器,需要实现HandlerInterceptor接口

自定义拦截器

controller中的方法

@Controller
@RequestMapping("/dept")
public class DeptController {

    public String finaAll(){
        System.out.println("controller方法执行了...");
        return "suc";
    }
}

建类,实现HandlerInterceptor接口,重写需要的方法
public class MyInterceptor implements HandlerInterceptor {

    /**
     * 拦截器拦截后执行的方法
     * boolean true放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器preHandle方法执行了...");
        // 拦截,不放行
        //return false;
        //放行
        return true;
    }
}

在springmvc.xml中配置拦截器类

<mvc:interceptors>
    <mvc:interceptor>
        <!--该拦截器拦截哪些资源-->
        <mvc:mapping path="/dept/**"/>
        <!--哪些资源不想拦截
        <mvc:exclude-mapping path="" />
        -->
        <!--拦截器对象-->
        <bean class="com.qcby.controller.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

配置多个拦截器
再编写一个拦截器的类
配置2个拦截器

<!--配置拦截器们-->
    <mvc:interceptors>
        <!--配置拦截器-->
        <mvc:interceptor>
            <!--该拦截器拦截哪些资源-->
            <mvc:mapping path="/dept/**"/>
            <!--哪些资源不想拦截
            <mvc:exclude-mapping path="" />
            -->
            <!--拦截器对象-->
            <bean class="com.qcbyjy.demo4.MyInterceptor2" />
        </mvc:interceptor>
        <!--配置拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.qcbyjy.demo4.MyInterceptor3" />
        </mvc:interceptor>
    </mvc:interceptors>

HandlerInterceptor接口中的方法

preHandle方法是controller方法执行前拦截的方法
1.可以使用request或者response跳转到指定的页面
2.return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
3.return false不放行,不会执行controller中的方法。
postHandle是controller方法执行后执行的方法,在JSP视图执行前。
1.可以使用request或者response跳转到指定的页面
2.如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
postHandle方法是在JSP执行后执行
request或者response不能再跳转页面了


原文地址:https://blog.csdn.net/m0_62902381/article/details/136995434

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!