IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java - 框架 - SpringMVC -> 正文阅读

[Java知识库]Java - 框架 - SpringMVC

Java - 框架 - SpringMVC

一、项目搭建

  1. pom.xml

    <!--maven依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.17.RELEASE</version>
    </dependency>
    </dependencies>
     <!-- fileUpload 解析上传的文件用到的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>
    <!--servlert依赖-->
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- tomcat插件 -->
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!-- 端口号 -->
                <port>8082</port>
                <!-- /表示访问路径 省略项目名 -->
                <path>/</path>
                <!-- 设置编码方式 -->
                <uriEncoding>utf-8</uriEncoding>
            </configuration>
        </plugin>
    </plugins>
    
  2. web.xml

    <filter>
        <filter-name>encodeFilter</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>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>encodeFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--  注册前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!--关联配置文件-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    如果报错:

    The content of element type “web-app” must match "(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resource-env-ref*,resource-ref*,security-constraint*,login-config?,security-role*,env-entry*,ejb-ref*,ejb-local-ref*)

    解决方法:

    将filter代码放到servlet上面,就可以解决

    原理:

    按照web.xml中的映射配置顺序按照配置条件从后向前调用第一个满足条件的Servlet,调用之前事先执行满足条件的Filter,不存在层次调用Servlet问题

    参考文章:

    Filter与Servlet的区别与联系_随风飘扬-CSDN博客_filter和servlet

  3. applicationContext.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: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/mvc   http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--开启扫描-->
        <context:component-scan base-package="com.spring"></context:component-scan>
    
        <!--开启springmvc注解的使用-->
        <mvc:annotation-driven/>
    
        <!--配置视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--设值前缀-->
            <property name="prefix" value="/"/>
            <!--设值后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    
  4. Controller.java

    @Controller//
    // 将Controller交给容器管理
    @RequestMapping("/user")
    //头部的mapping可以省略,实际访问地址为tomcat后面的地址加/user/query
    public class UserController {
        //地址实例:http:localhost:8082/mvc/user/query
        //前面的端口和mvc配置在tomcat中
        @RequestMapping("/query")
        public String query(){
            System.out.println("query.........");
            return "index";
        }
    }
    

二、SpringMVC响应请求

2.1 不响应请求

如果用户提交了请求后服务端不需要给客户端一个响应,那么我们可以指定返回类型为void同时在方法头部添加@ResponseBody注解即可

@RequestMapping("/save")
@ResponseBody
public void add(){
    System.out.println("save ..... ");
}

2.2 响应返回字符串

我们可以在处理方法的最后返回一个要跳转的页面地址”/“不要漏了

@RequestMapping("/query")
public String query(){
    System.out.println("query ..... ");
    return "index";
}

2.3 返回ModelAndView

我们也可以直接返回一个ModelAndView对象

@RequestMapping("/delete")
public ModelAndView delete(){
    System.out.println("delete ..... ");
    ModelAndView mm = new ModelAndView();
    mm.setViewName("/index.jsp");
    return mm;
}

2.4 重定向跳转

有些情况下重定向跳转也是我们开发中必须使用的形式

@RequestMapping("/update")
public String update(){
    System.out.println("update ..... ");
    return "redirect:/user/query";
}

2.5 通过HttpServletResponse响应

仅仅只需要在方法的形参中声明这两个变量即可~

@RequestMapping("/fun1")
public void fun1(HttpServletRequest request
                 ,HttpServletResponse response) throws Exception {
    // response.sendRedirect("/mvc/test/fun1");
    System.out.println("fun1 ...");
    request.getRequestDispatcher("/index.jsp").forward(request,response);
}

三、SpringMVC接收请求

3.1 基本数据类型

直接在形参中声明要接收的数据,默认情况下形参必须和传过来的数据参数名一致

@RequestMapping("/query")
public String query(@RequestParam(value = "ids",required = true,defaultValue = "123") Integer id, String name){
    System.out.println("query ..... " + id + ":" + name);
    return "/index.jsp";
}

3.2 对象接收

如果传递过来的数据比较多,那么我们可以通过一个自定义的对象来接收

@RequestMapping("/save")
public String add(User user){
    System.out.println("save ..... " + user);
    return "/index.jsp";
}
@Component
public class User {
    private Integer id;
    private String name;
    //省略getter、setter、toString
}

3.3 通过数组接收

如果有多个名称相同的数据提交,我们可以使用数组的方式来接收

@RequestMapping("/delete")
public String delete(String[] loves){
    System.out.println("delete ..... ");
    if(loves !=null){
        for(String l : loves){
            System.out.println(l);
        }
    }
    return "/index.jsp";
}

注意:在形参中我们不能够通过集合的方式来获取传递的参数

在自定义对象中可以使用集合获取数组的形式来接收请求的参数

3.4 自定义转换器

有时候客户端传递过来特殊类型的数据,SpringMVC中提供的默认的转换器不能支持该转换,此时我们就需要自定义转换器

package com.gupaoedu.convert;

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateConvert implements Converter<String,Date> {
    @Override
    public Date convert(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return sdf.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

applicationContext.xml配置文件

<!-- 配置转换器 -->
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"
      id="formattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.gupaoedu.convert.DateConvert"/>
        </set>
    </property>
</bean>

四、SpringMVC返回数据

4.1 ModelAndView传递

@RequestMapping("/query")
public ModelAndView query(){
    System.out.println("query ..... ");
    ModelAndView mm = new ModelAndView();
    mm.setViewName("/user.jsp");
    mm.addObject("msg","msg.....");
    return mm;
}

然后在jsp页面中通过EL表达式获取传递的信息

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  hello<br>
  ${msg}
</body>
</html>

4.2 通过Map对象传值

ModelAndView使用起来稍微有点复杂,我们可以通过Map来简化操作

@RequestMapping("/save")
public String add(Map<String,Object> map){
    System.out.println("save ..... ");
    map.put("msg","map ...msg");
    return "/user.jsp";
}

4.3 通过Model来接收

@RequestMapping("/delete")
public String delete(Model model){
    System.out.println("delete ..... ");
    model.addAttribute("msg","model ...msg");
    return "/index.jsp";
}

4.4 通过ModelMap响应数据

@RequestMapping("/update")
public String update(ModelMap mm){
    System.out.println("update ..... ");
    mm.put("msg","ModelMap ... msg");
    return "/index.jsp";
}

前面介绍的多种方式的数据都是会被保存在request作用域中,如果我们同时需要将数据保存在Session对象中,我们只需要在类的头部添加一个@SessionAttributes注解即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQSIlAwA-1635304366727)(C:/Users/lWX1096948/Downloads/8.5 SpringMVC之高级进阶/8.5 SpringMVC之高级进阶/01-课件笔记/img/1598431973792.png)]

五、SpringMVC文件

5.1 文件上传

5.1.1 依赖的引入

 <!-- fileUpload 解析上传的文件用到的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>

5.1.2 表单页面

提交的方式必须是post 方式,提交的数据的类型必须是二进制文件

<html>
<body>
<h2>Hello World!</h2>
    <form action="/user/save" method="post" enctype="multipart/form-data">
        姓名:<input type="text" name="username"><br>
        头像:<input type="file" name="headImg"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

5.1.3 控制处理

提交的文件我们可以通过 MultipartFile 类型来接收

@RequestMapping("/save")
public String add(MultipartFile headImg,String username) throws IOException {
    System.out.println(username);
    System.out.println("文件名称:" + headImg.getOriginalFilename());
    headImg.transferTo(new File("d:/" + headImg.getOriginalFilename()));
    return "/index.jsp";
}

5.1.4 配置文件处理

<!--  文件上传的解析器-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
    <property name="maxUploadSize">
        <value>5242880</value>
    </property>
</bean>

5.2 文件下载

@RequestMapping("/download")
public void download(HttpServletRequest request,
                     HttpServletResponse response){
    File file = new File("d://PC软件安装与环境准备.docx");
    // 设置响应的头和客户端保存文件名
    response.setCharacterEncoding("utf-8");
    response.setContentType("multipart/form-data");
    try {
        //header中只支持ASCII ,如果文件名有中文,需要进行URL转码
        //fileName = URLEncoder.encode(fileName,"utf-8");
        response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(file.getName(),"utf-8"));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    try {
        // 打开本地文件流
        InputStream in = new FileInputStream(file);
        // 激活下载的流
        ServletOutputStream out = response.getOutputStream();
        byte[] b = new byte[1024];
        int num = 0;
        while ((num = in.read(b)) != -1){
            out.write(b,0,num);
        }
        out.close();
        in.close();
    }catch (Exception e){
        e.printStackTrace();
    }
}

5.3文件展示

默认的情况下在SpringMVC中只能访问jsp页面,其他的都会被DispatchServlet拦截,原因是DispatchServlet配置的时候用的/ 覆盖掉了defaultservlet所做的工作,

  1. 重新覆写DispatchServlet
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>

六、Controller数据验证

6.1 校验注解实现

  1. 引入依赖

    SpringMVC本身是没有提供校验框架的,我们需要使用Hibernate提供的校验框架

    <dependency>
      	<groupId>org.hibernate</groupId>
      	<artifactId>hibernate-validator</artifactId>
      	<version>5.3.0.Alpha1</version>
    </dependency>
    
  2. 在配置文件中注册对应的校验框架

    <!-- 开启SpringMVC注解的使用,在这边加上校验-->
    <mvc:annotation-driven validator="validated"/>
    
    <!-- 配置验证框架 -->
    <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="localValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <property name="validationMessageSource" ref="messageSource" />
    </bean>
    
    <bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
        <property name="basename" value="classpath:volidata.properties"/>
        <property name="fileEncodings" value="utf-8"/>
        <property name="cacheSeconds" value="120"/>
    </bean>
    
  3. 实现pojo对象

    import lombok.Data;
    import org.hibernate.validator.constraints.Length;
    import org.hibernate.validator.constraints.NotBlank;
    import org.springframework.stereotype.Component;
    
    import javax.validation.constraints.NotNull;
    
    @Component
    @Data
    public class User {
    
        //自定义报错提示
        @Length(message = "name长度为3-6",max = 6,min = 3)
        private String name;
    
        //读取配置文件中的提示
        @NotBlank(message = "{user.sex.isnull}")
        private String sex;
    
        @NotNull(message = "id不能为空")
        private Integer id;
    }
    
  4. Controller对象实现

    @RequestMapping("add")
    public ModelAndView add(@Validated User user, BindingResult br){
        //在需要校验的对象前面加上`@Validated`注解
        System.out.println(user);
        ModelAndView modelAndView = new ModelAndView();
        List<ObjectError> errors = br.getAllErrors();
        modelAndView.setViewName("/user.jsp");
        for (ObjectError error :errors){
            System.out.println(error.getDefaultMessage());
            modelAndView.addObject("error",error.getDefaultMessage());
        }
        if (errors.size()>0){
            return modelAndView;
        }
        else{
            modelAndView.addObject("id",user.getId());
            modelAndView.addObject("name",user.getName());
            modelAndView.addObject("sex",user.getSex());
        }
        return modelAndView;
    }
    
  5. jsp对象实现

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <body>
    <h2>Hello World!</h2>
    <form action="/test/add" method="get" >
        id:<input type="text" name="id"><br>
        name:<input type="text" name="name"><br>
        sex:<input type="text" name="sex"><br>
        <input type="submit" value="提交">
    </form>
    
    <h1>${error}</h1>
    id:${id}<br>
    name:${name}<br>
    sex:${sex}
    </body>
    </html>
    
  6. 注意点:

    1. 如果在实现过程中发现配置文件中读取的内容是乱码,调整idea的配置文件编码格式

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o25FdbGS-1635435032548)(C:/Users/Apricity/AppData/Roaming/Typora/typora-user-images/image-20211028231154766.png)]

6.2 常用校验注解

验证规则

注解说明
@Null被注解的元素必须为 null
@NotNull被注解的元素必须不为 null
@AssertTrue被注解的元素必须为 true
@AssertFalse被注解的元素必须为 false
@Min(value)被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=)被注解的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注解的元素必须是一个数字,其值必须在可接受的范围内
@Past被注解的元素必须是一个过去的日期
@Future被注解的元素必须是一个将来的日期
@Pattern(regex=,flag=)被注解的元素必须符合指定的正则表达式
@NotBlank(message =)验证字符串非null,且长度必须大于0
@Email被注解的元素必须是电子邮箱地址
@Length(min=,max=)被注解的字符串的大小必须在指定的范围内
@NotEmpty被注解的字符串的必须非空
@Range(min=,max=,message=)被注解的元素必须在合适的范围内

6.3 分组校验

分组验证解决的是不同的同一个POJO对象在不同的场景用适用不同的验证规则

  1. 实现分组接口

    public interface MyVal1 {
    }
    
    public interface MyVal2 {
    }
    
    
  2. 实现bean对象

    @Component
    @Data
    public class User {
    
        //自定义报错提示
        @Length(message = "name长度为3-6",max = 6,min = 3,groups = MyVal1.class)
        private String name;
    
        //读取配置文件中的提示
        @NotBlank(message = "{user.sex.isnull}",groups = {MyVal1.class})
        private String sex;
    
        @NotNull(message = "id不能为空",groups = {MyVal1.class, MyVal2.class})
        private Integer id;
    }
    
  3. 实现分组校验

    @RequestMapping("/save")
    public String add(@Validated({MyVal1.class}) User user, BindingResult br, Model model) throws IOException {
        System.out.println("save ....");
        List<ObjectError> allErrors = br.getAllErrors();
        for (ObjectError error:allErrors){
            System.out.println(error.getDefaultMessage());
        }
        return "/index.jsp";
    }
    
    @RequestMapping("/update")
    public String update(@Validated({MyVal2.class}) User user, BindingResult br, Model model) throws IOException {
        System.out.println("update ....");
        List<ObjectError> allErrors = br.getAllErrors();
        for (ObjectError error:allErrors){
            System.out.println(error.getDefaultMessage());
        }
        return "/index.jsp";
    }
    

七、SpringMVC拦截器

定义自己的拦截器类

package com.springmvc.interceptor;

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

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

public class MyInterceptor implements HandlerInterceptor {

    /**
     * 在自定义控制器执行之前执行
     * @param request
     * @param response
     * @param handler
     * @return
     *    false  拦截
     *    true 放过
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("preHandle....");
        return true;
    }

    /**
     * 自定义控制器执行后执行
     *      在返回ModelAndView之前执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     */
    @Override
    public void postHandle(HttpServletRequest request
            , HttpServletResponse response
            , Object handler, ModelAndView modelAndView) {

        System.out.println("postHandle ....");
    }

    /**
     * 自定义控制器执行后执行
     *     在返回ModelAndView之后执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     */
    @Override
    public void afterCompletion(HttpServletRequest request
            , HttpServletResponse response
            , Object handler, Exception ex) {
        System.out.println("afterCompletion....");
    }
}

在配置文件中加上自定义的拦截器

<!-- 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.springmvc.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 12:51:50  更:2021-10-29 12:53:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:47:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码