【SSM框架 三】SpringMVC
admin
2024-03-17 23:35:32
0

文章目录

  • 三、SpringMVC
    • 1、回顾MVC
    • 2、初始springMVC
    • 3、使用注解开发
    • 4、Controller总结
      • 4.1 实现controller接口方式(不建议使用)
      • 4.2 使用注解实现
    • 5、RestFul风格
      • 5.1 传统方式操作资源
      • 5.2 使用RestFul操作资源
    • 6、重定向和转发
    • 7、接收请求参数及回显
      • 7.1 处理提交数据
      • 7.2 数据显示到前端
    • 8、乱码问题
    • 9、JSON
      • 9.1 响应直接返回字符串
      • 9.2 解析工具jackson
      • 9.3 返回的json数据乱码解决
      • 9.4 几种类型值的返回
      • 9.5 解析工具fastjson
    • 10、SSM整合
      • 10.1 搭建框架
      • 10.2 DAO层
      • 10.2 Service层
      • 10.3 Spring整合Dao
      • 10.4 Spring整合Sevice
      • 10.5 SpringMVC
      • 10.6 Controller层
      • 10.6 编写页面
    • 11、AJAX
      • 11.1 简介
      • 11.2 Ajax异步加载数据
      • 11.3 Ajax验证用户名
    • 12、拦截器
      • 12.1 介绍
      • 12.2 登录权限验证(拦截)
    • 13、文件上传和下载
      • 13.1 文件上传
      • 13.2 文件下载

三、SpringMVC

1、回顾MVC

MVC:模型(dao,service) 视图(jsp) 控制(servlet)

  1. 用户发送请求
  2. Servlet接收用户请求数据,并调用对应的业务逻辑方法
  3. 业务处理完毕,返回更新后的数据给Servlet
  4. Servlet转向jsp,由jsp来渲染页面
  5. 响应给前端更新后的页面

职责分析

1. Controller:控制器- 取得表单数据- 调用业务逻辑- 转向指定页面
2. Model:模型- 业务逻辑- 保存数据的状态
3. View:视图- 显示页面 

2、初始springMVC

我们可以将springMVC中使用的所有bean注册到spring中

Spring的web框架围绕DispatcherServlet设计,DispatcherServlet它的作用是将请求分发到不同的处理器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YzlFUPG8-1670147240885)(D:\Java\Markdown\java学习笔记\05第五阶段:SSM框架.assets\image-20221124150719846.png)]

1.导入依赖

org.springframeworkspring-webmvc5.3.23


javax.servletjstl1.2

  1. 配置dispatcherServlet

web.xml


springmvcorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:springmvc-servlet.xml1springmvc/

3.编写spring的配置文件

springmvc-servlet.xml




4.编写Controller

package com.daban.controller;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();//业务代码mv.addObject("msg","这是响应的数据");//设置视图跳转mv.setViewName("hello");return mv;}
}

5.编写显示页面(jsp)

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

Title


${msg}


6.启动tomcat测试

如果报404,检查一下编译输出目录out有没有lib包导出

3、使用注解开发

1.新建一个maven项目,导入web框架

2.编写web.xml


springmvcorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:springmvc-servlet.xml1springmvc/

3.编写springmvc-servlet.xml




4.创建Controller

package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HelloController {@RequestMapping("/hello")//请求路径public String hello(Model model){//封装数据model.addAttribute("msg","我是注解开发");return "hello";//返回的视图名字(跳转的视图)}
}

5.视图

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

Title


${msg}


注解扩展:

@Controller
@RequestMapping("/all")//如果给类加上该注解,则url变成http://localhost:8080/all/hello
@RestController//标识该类不会被视图解析器解析,返回的是一个字符串
public class HelloController {@RequestMapping("/hello")//请求路径public String hello(Model model){//封装数据model.addAttribute("msg","我是注解开发");return "hello";//返回的视图名字(跳转的视图)}
}

4、Controller总结

  • 控制器负责提供访问应用程序的行为,可以通过接口定义和注解定义两种方式实现
  • 控制器负责解析用户的请求,将其转换为模型
  • SpringMVC中的控制器可以包含多个方法

4.1 实现controller接口方式(不建议使用)

  1. web.xml配置DispatcherServlet
  2. springmvc-servlet.xml配置(处理器映射(省略),处理器适配器(省略),视图解析器)
  3. 创建类实现Controller接口,方法中封装数据,视图跳转
  4. springmvc-servlet.xml中注册控制器,注意注册控制器的id就是请求的路径
  5. 编写视图显示页面

4.2 使用注解实现

  1. web.xml配置DispatcherServlet
  2. springmvc-servlet.xml配置(扫描包,静态资源过滤,注解驱动生效,视图解析器)
  3. 创建类,使用@Controller注解标注该类是控制器
  4. 控制器中创建一个方法,该方法的返回值就是需要跳转的页面,参数为Model类型,使用参数封装数据
  5. 使用@RequestMapping(“/t2”)注解来设置该方法被请求的路径
  6. 编写视图显示页面

5、RestFul风格

概念:RestFul是一个资源定位及资源操作的风格,不是标准,也不是协议,是一种风格

5.1 传统方式操作资源

使用不同的地址,带不同的参数来实现

原始方式:http://localhost:8080/r?a=1&b=2

@Controller
public class RestFulTest {//http://localhost:8080/r?a=1&b=2@RequestMapping("/r")public String test(int a, int b , Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}

5.2 使用RestFul操作资源

通过不同的请求方式实现,使用相同的地址实现不同的请求

更改后url:http://localhost:8080/r/1/2

@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@RequestMapping("/r/{a}/{b}")public String test(@PathVariable int a, @PathVariable int b , Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}

限定请求方式一

@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@RequestMapping(value = "/r/{a}/{b}",method = RequestMethod.POST)public String test(@PathVariable int a, @PathVariable String b , Model model){String res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}

限定请求方式二

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

@Controller
public class RestFulTest {//http://localhost:8080/r/1/2@GetMapping("/r/{a}/{b}")public String test(@PathVariable int a, @PathVariable String b , Model model){String res = a+b;model.addAttribute("msg","结果为:"+res);return "test1";}
}

这样通过限定不同的请求方式,来使同一个地址,执行不同的方法

6、重定向和转发

return "forward:/login.jsp"; //转发到 根目录/login.jsp
return "forward:/login";     //转发到 根目录/login
return "redirect:/login.jsp";//重定向到  根目录/login.jsp
return "redirect:/login";    //重定向到  根目录/login
return "login.jsp";          //转发到,根目录/WEB-INF/jsp/login.jsp.jsp,错误用法
return "login";              //转发到  根目录/WEB-INF/jsp/login
@Controller
public class DispatcherTest {@RequestMapping("/d/t1")public String test3(Model model){model.addAttribute("msg","t3");//默认是转发,加上redirect:就是重定向return "redirect:/index.jsp";}
}

WEB-INF下的文件无法重定向

​ WEB-INF是安全目录,客户端无法访问,而重定向就相当于用户直接从客户端访问了的路径,自然就不可以啦,只有程序内部转发的时候才能转发到WEB-INF下的JSP

7、接收请求参数及回显

7.1 处理提交数据

  1. 提交域名称和处理方法的参数名一致

    //http://localhost:8080/hello?name=123
    public String test3(String name,Model model){return "test1";
    }
    
  2. 提交域名称和处理方法的参数名不一致

    //http://localhost:8080/hello?name=123
    public String test3(@RequestParam("name") String username, Model model){return "test1";
    }
    
  3. 提交的是一个对象

    创建一个实体类,实体类的属性就是提交的参数

    //http://localhost:8080/hello?name=ss&age=12
    public String test3(User user, Model model){return "test1";
    }
    

如果使用对象的话,前端传递的参数名必须和实体类的属性名一致,否则会为null

7.2 数据显示到前端

  1. 使用ModelAndView

    可以在存储数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转

    public ModelAndView test3(ModelAndView mv){mv.addObject("msg","ModelAndView");mv.setViewName("test1");return mv;
    }
    
  2. 使用Model

    只有寥寥的几个方法,只适用于存储数据,简化操作

    public String test3(Model model){model.addAttribute("msg","信息");return "test1";
    }
    
  3. 使用ModelMap

    继承了LinkedMap,除了实现自身的一些方法,同样继承了LinkedMap的方法,操作更丰富

    public String test3(ModelMap map){map.addAttribute("msg","map");return "test1";
    }
    

8、乱码问题

加上过滤器,这里一定要注意"/“和”/*"的区别

/ :匹配所有请求,不会去匹配jsp页面
/* :匹配所有请求,包括jsp页面
encodingorg.springframework.web.filter.CharacterEncodingFilterencodingutf-8

encoding/*

9、JSON

json是js对象的字符串表示形式,它使用文本表示一个js对象信息,本质是一个字符串

var obj = {name:"zhangsan",age:12};//这是对象
var json ='{{name:"zhangsan",age:12}}'//这是json字符串

json和js对象互相转化

var obj1 = JSON.parse(json);//json字符串转js对象
var json1 = JSON.stringify(obj);//js对象转json字符串

9.1 响应直接返回字符串

@RestController //标识该类不会被视图解析器解析,返回的是一个字符串

@ResponseBody //标识该方法不会被视图解析器解析,返回的是一个字符串

9.2 解析工具jackson

对象使用toString输出样式

User{name='张三', age=12, sex='男'}

对象使用jackson转换成json字符串输出样式

{"name":"张三","age":12,"sex":"男"}
@Controller
public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {User user = new User("张三",12,"男");ObjectMapper mapper = new ObjectMapper();String s = mapper.writeValueAsString(user);return s;}
}

9.3 返回的json数据乱码解决

后端响应给前端的字符串乱码解决

@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")

或这个spingmvc-servlet.xml文件中配置



9.4 几种类型值的返回

  1. 列表返回

    @Controller
    public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ArrayList list = new ArrayList<>();ObjectMapper mapper = new ObjectMapper();User user = new User("张三",12,"男");User user1 = new User("张三1",12,"男");User user2 = new User("张三2",12,"男");list.add(user);list.add(user1);list.add(user2);return mapper.writeValueAsString(list);}
    }返回值:[{"name":"张三","age":12,"sex":"男"},{"name":"张三1","age":12,"sex":"男"},{"name":"张三2","age":12,"sex":"男"}]
    
  2. 时间返回

    @Controller
    public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();Date date = new Date();return mapper.writeValueAsString(date);}
    }返回值:1669365101815
    
    @Controller
    public class UserController {@RequestMapping("/j1")@ResponseBodypublic String json() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//设置一个我们喜欢的时间格式SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//关闭ObjectMapper的自动转换时间格式功能mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);//设置使用自己的时间格式mapper.setDateFormat(dateFormat);Date date = new Date();return mapper.writeValueAsString(date);}
    }返回值:"2022-11-25 04:41:45"
    

9.5 解析工具fastjson

依赖

com.alibabafastjson2.0.19

//java对象转json字符串
String s = JSON.toJSONString(list);
System.out.println("java对象转json字符串(列表):"+s);
String us = JSON.toJSONString(user);
System.out.println("java对象转json字符串(对象):"+us);
//json字符串转Java对象
JSONObject javaObj = JSON.parseObject(us);
System.out.println("json字符串转Java对象:"+javaObj);
//java对象转json对象
JSONObject jsonObject = (JSONObject) JSON.toJSON(user1);
System.out.println("java对象转json对象:"+jsonObject);
//json对象转java对象
User user3 = JSON.toJavaObject(jsonObject, User.class);
System.out.println("json对象转java对象:"+user3);

10、SSM整合

10.1 搭建框架

  1. 创建一个数据库

    CREATE DATABASE `ssmbuild`;USE `ssmbuild`;
    DROP TABLE IF EXISTS `books`;CREATE TABLE `books`(`bookID`  INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',`bookName` VARCHAR(100) NOT NULL COMMENT '书名',`bookCounts` VARCHAR(11) NOT NULL COMMENT '数量',`detail` VARCHAR(200) NOT NULL COMMENT '描述',KEY `bookID` (`bookID`)
    )ENGINE INNODB DEFAULT CHARSET=utf8;INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`) 
    VALUES
    (1,'三国演义',10,'三国'),
    (2,'西游记',8,'孙悟空'),
    (3,'红楼梦',32,'贾府,林黛玉'),
    (4,'水浒传',6,'梁山好汉三结义'),
    (5,'三体',43,'科技之光'),
    (6,'射雕英雄传',98,'金庸大作');
    
  2. 创建一个Maven项目

    导入依赖

    
    junitjunit4.12
    
    
    mysqlmysql-connector-java5.1.47
    
    
    com.mchangec3p00.9.5.2
    
    
    javax.servletservlet-api2.5
    
    javax.servlet.jspjsp-api2.2
    
    javax.servletjstl1.2
    
    
    org.mybatismybatis3.5.11
    
    org.mybatismybatis-spring2.0.7
    
    
    org.springframeworkspring-webmvc6.0.0
    
    org.springframeworkspring-jdbc6.0.0
    
    
  3. 创建配置文件mybatis-config.xml

    
    
    
    
  4. 创建数据源database.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=123456
    
  5. 创建spring空配置文件ApplicationContext.xml

    
    
    

10.2 DAO层

  1. 创建books实体类

    package com.daban.pojo;public class Books {private int bookID;private String bookName;private String bookCounts;private String detail;public Books(int bookID, String bookName, String bookCounts, String detail) {this.bookID = bookID;this.bookName = bookName;this.bookCounts = bookCounts;this.detail = detail;}public int getBookID() {return bookID;}public void setBookID(int bookID) {this.bookID = bookID;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getBookCounts() {return bookCounts;}public void setBookCounts(String bookCounts) {this.bookCounts = bookCounts;}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}@Overridepublic String toString() {return "Books{" +"bookID=" + bookID +", bookName='" + bookName + '\'' +", bookCounts='" + bookCounts + '\'' +", detail='" + detail + '\'' +'}';}
    }
    
  2. 创建接口BookMapper.java

    package com.daban.dao;import com.daban.pojo.Books;
    import org.apache.ibatis.annotations.Param;import java.util.List;public interface BookMapper {//增加一本书int addBook(Books books);//删除一本书int deleteBookById(@Param("bookId") int id);//修改一本书int updateBook(Books books);//查询一本书Books queryBookById(@Param("bookId") int id);//查询全部书List queryAllBook();List queryBookByName(String bookName);
    }
    
  3. 创建接口映射文件BookMapper.xml

    
    
    insert into ssmbuild.books(bookName, bookCounts, detail)values (#{bookName},#{bookCounts},#{detail});delete from ssmbuild.books where bookID = #{bookId};update ssmbuild.booksset bookName = #{bookName},bookCounts=#{bookCounts},detail=#{detail}where bookID = #{bookID};
    
    
  4. 在mybatis配置文件中注册mapper

    
    
    

10.2 Service层

  1. 创建接口BookService.java

    package com.daban.service;import com.daban.pojo.Books;
    import java.util.List;public interface BookService {//增加一本书int addBook(Books books);//删除一本书int deleteBookById(int id);//修改一本书int updateBook(Books books);//查询一本书Books queryBookById(int id);//查询全部书List queryAllBook();List queryBookByName(String bookName);
    }
    
  2. 创建接口的实现类BookServiceImp.java

    package com.daban.service;import com.daban.dao.BookMapper;
    import com.daban.pojo.Books;import java.util.List;public class BookServiceImp implements BookService{//业务层调dao层private BookMapper bookMapper;public void setBookMapper(BookMapper bookMapper) {this.bookMapper = bookMapper;}@Overridepublic int addBook(Books books) {return bookMapper.addBook(books);}@Overridepublic int deleteBookById(int id) {return bookMapper.deleteBookById(id);}@Overridepublic int updateBook(Books books) {return bookMapper.updateBook(books);}@Overridepublic Books queryBookById(int id) {return bookMapper.queryBookById(id);}@Overridepublic List queryAllBook() {return bookMapper.queryAllBook();}@Overridepublic List queryBookByName(String bookName) {return bookMapper.queryBookByName(bookName);}}
    

10.3 Spring整合Dao

  1. 创建spring-dao.xml

    
    
    
    

10.4 Spring整合Sevice

  1. 创建spring-service.xml

    
    
    

10.5 SpringMVC

  1. 增加web支持

  2. 配置web.xml

    这里有一个兼容文件,在配置DispatcherServlet时报错,把spring-webmvc依赖版本改成5.3.23

    
    springmvcorg.springframework.web.servlet.DispatcherServletcontextConfigLocationclasspath:ApplicationContext.xml1springmvc/encodingorg.springframework.web.filter.CharacterEncodingFilterencodingutf-8encoding/*15
    
    
  3. 创建配置spring-mvc.xml

    
    
    
    
  4. 将spring配置文件统一到ApplicationContext中

    
    
    
    

10.6 Controller层

  1. 创建一个控制类BookController.java

    package com.daban.controller;import com.daban.pojo.Books;
    import com.daban.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;@Controller
    @RequestMapping("/book")
    public class BookController {@Autowired@Qualifier("BookServiceImp")private BookService bookService;//查询所有书籍@RequestMapping("/allBook")public String allBook(Model model){List books = bookService.queryAllBook();model.addAttribute("boos",books);return "allBook";}//跳转到新增书籍页面@RequestMapping("/addBookPage")public String toAddBookPage(){return "addBookPage";}//执行添加书籍@RequestMapping("/addBook")public String addBook(Books books){//System.out.println(books);bookService.addBook(books);return "redirect:/book/allBook";//return "allBook";}//跳转到书籍修改页@RequestMapping("/updateBookPage")public String toUpdateBookPage(int id,Model model){Books book = bookService.queryBookById(id);model.addAttribute("book",book);return "updateBookPage";}//执行修改书籍@RequestMapping("/updateBook")public String updateBook(Books books){System.out.println(books);bookService.updateBook(books);return "redirect:/book/allBook";}//删除数据@RequestMapping("/deleteBook")public String deleteBook(int id){bookService.deleteBookById(id);return "redirect:/book/allBook";}//查询书籍@RequestMapping("/queryBookByName")public String queryBook(String queryBookName,Model model){List books = bookService.queryBookByName("%"+queryBookName+"%");//System.out.println(books);if(books.size()==0){model.addAttribute("error","没有查到内容");}else{model.addAttribute("boos",books);}return "allBook";}
    }
    

10.6 编写页面

页面其实和Controller层同步写的

  1. 编写首页index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    首页

    全部书籍

  2. 编写allbook.jsp

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    查询全部书籍
    
    
    

    书籍列表——————显示所有书籍

    书籍编号书籍名称书籍数量书籍描述操作
    ${book.bookID}${book.bookName}${book.bookCounts}${book.detail}修改  | 删除
  3. 编写addBookPage.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    添加书籍
    
    
    

    添加书籍

  4. 编写updateBookPage.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    修改书籍
    
    
    

    修改书籍

    <%-- 一定要注意这个隐藏的字段,没有id没办法修改--%>

11、AJAX

11.1 简介

他是一个在无需刷新网页的情况下,能够更新部分网页数据的技术

Ajax的核心是XMLHttpRequest对象(XHR)

jQuery提供了多个与ajax相关的方法

jQuery静态资源找不到问题

  • spring配置文件没有加这个语句,过滤静态资源使不经过servlet
  • 增加了静态资源后必须重新启动服务器
function a(){$.ajax({//请求地址url:"${pageContext.request.contextPath}/a2",//请求数据data:{"name":$("#username").val()},//成功回调函数,带返回数据data,这个参数是键值对success:function (data) {alert(data);console.log("执行的成功的回调函数");},//失败回调函数error:function () {console.log("执行的失败的回调函数");}})
}

11.2 Ajax异步加载数据

  • 实体类

    package com.daban.pojo;import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;@Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {private String name;private int age;private String sex;
    }
    
  • 控制层

    @RequestMapping("/a3")
    public List a3(){ArrayList userList = new ArrayList<>();userList.add(new User("张三",32,"男"));userList.add(new User("李四",12,"女"));userList.add(new User("王五",52,"男"));userList.add(new User("王留",22,"男"));return userList;
    }
    
  • 页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    Title
    
    
    姓名年龄性别

11.3 Ajax验证用户名

  • 控制层

    @RequestMapping(value = "/a4",produces = "text/html;charset=utf-8")
    public String a4(String name){if(name.equals("ss")){return "OK";}elsereturn "用户名不存在";
    }
    
  • 页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    Title
    
    用户名:
    密码:

12、拦截器

12.1 介绍

SpringMVC的拦截器类似于servlet中的过滤器Filter

拦截器是AOP思想的具体应用,意思拦截器就是横切进去的

拦截器只会拦截访问控制器的方法,静态页面放行,自带静态资源过滤

自定义拦截器(实现HandlerInterceptor接口):

package com.daban.config;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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("===========拦截前===========");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("===========拦截后===========");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("===========清理===========");}
}

在springmvc中配置拦截器,才能使用



12.2 登录权限验证(拦截)

控制器:

@RequestMapping("/login")
public String login(HttpSession session, String name, String pwd, Model model){//如果name或pwd为空,则说明是使用session越权登录,正常跳转//否则是正常登陆,需要验证用户名密码if(name==null || pwd==null){return "main";}else {if(name.equals("zj") && pwd.equals("123")){session.setAttribute("username",name);return "main";}else{model.addAttribute("msg","账号或密码错误");return "forward:/login.jsp";}}}
@RequestMapping("/logout")
public String logout(HttpSession session){session.removeAttribute("username");return "redirect:/login.jsp";
}

拦截器:

package com.daban.config;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();Object username = session.getAttribute("username");String name = request.getParameter("name");String pwd = request.getParameter("pwd");//如果name和pwd都不为空,则是正常登录,需要放行if (name!=null && pwd!=null){return true;}//如果name和pwd字段为空,则表示越权登陆,就需要判断是否有session//如果有session则放行,没session则重定向if(username!=null){return true;}else {response.sendRedirect("/login.jsp");}return false;}
}

13、文件上传和下载

要使用spring的上传功能,需要上下文中配置MultipartResolver

前端表单必须是post,enctype设置为multipart/form-data

表单属性enctype说明

  • application/x-www=form-urlencoded,默认方式,只处理表单中的value
  • multipart/form-data,以二进制流处理表单,把文件内容封装到请参数中,不会对字符编码
  • text/plain,除了把空格转换成+号外,其他字符不做编码,这种适合表单发邮件

13.1 文件上传

步骤:

  1. 导入文件上传的jar包

    commons-fileuploadcommons-fileupload1.4
    
    javax.servletjavax.servlet-api4.0.1
    
    
  2. 写提交页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    $Title$
  3. spring配置文件中配置

    
    
    
    
  4. 写controller

    • 方法一

      package com.daban.controller;import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletRequest;
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.InputStream;@Controller
      public class FileController {//将表单中name属性为file的控件得到的文件封装成CommonsMultipartFile对象//批量上传,CommonsMultipartFile为数组即可//注意重点,CommonsMultipartFile必须加@RequestParam("file"),否则报空指针@RequestMapping("/upload")public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {//获取文件名String filename = file.getOriginalFilename();//如果文件为空,则直接回到首页System.out.println("文件名:"+filename);if("".equals(filename)){return "redirect:/index.jsp";}//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");//如果路径不存在,创建一个File realPath = new File(path);if(!realPath.exists()){realPath.mkdir();}System.out.println("上传路径:"+realPath);InputStream is = file.getInputStream();FileOutputStream fos = new FileOutputStream(new File(realPath, filename));int len=0;byte[] buffer = new byte[1024];while ((len=is.read(buffer))!=-1){fos.write(buffer,0,len);fos.flush();}is.close();fos.close();return "redirect:/index.jsp";}
      }
      
    • 方法二

      package com.daban.controller;import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.HttpServletRequest;
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      import java.io.InputStream;@Controller
      public class FileController {//将表单中name属性为file的控件得到的文件封装成CommonsMultipartFile对象//批量上传,CommonsMultipartFile为数组即可//注意重点,CommonsMultipartFile必须加@RequestParam("file"),否则报空指针@RequestMapping("/upload")public String upload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {//获取文件名String filename = file.getOriginalFilename();//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");//如果路径不存在,创建一个File realPath = new File(path);if(!realPath.exists()){realPath.mkdir();}//通过CommonsMultipartFile的方法直接写文件file.transferTo(new File(realPath+"/"+filename));return "redirect:/index.jsp";}
      }
      

13.2 文件下载

写controller

package com.daban.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;@Controller
public class FileController {@RequestMapping("/download")public String download(HttpServletRequest request, HttpServletResponse response) throws Exception {//要下载文件的地址String path = request.getServletContext().getRealPath("/upload");String fileName = "123.md";//设置响应头response.reset();//设置响应页面不缓存,清空bufferresponse.setCharacterEncoding("utf-8");//字符编码response.setContentType("multipart/form-data");//二进制流传输response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));File file = new File(path, fileName);FileInputStream fis = new FileInputStream(file);OutputStream os = response.getOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len=fis.read(buffer))!=-1){os.write(buffer,0,len);os.flush();}os.close();fis.close();return null;}
}

相关内容

热门资讯

银行间主要利率债午间走势分化 每经AI快讯,7月28日,银行间主要利率债午间走势分化,30年期国债“26超长特别国债04”收益率下...
2026海河国际消费论坛即将在... 2026海河国际消费论坛将于7月30日下午在天津启幕,目前各项筹备工作已全部就绪。本届论坛以“创新服...
原创 一... 前言 1942年的一天,一名身穿军装的年轻人,悄悄走到一位老妇人的面前。他脸上带着疲惫,眼神中却依然...
原创 曹... 八十岁的曹德旺,这几年在公开场合谈到房子这两个字,语气一次比一次冷。他早年那句"房子不过是钢筋水泥堆...
股息率近5.5%!港股红利低波... 7月28日,港股红利资产延续强势。截至13时48分,港股红利低波ETF招商(520550)涨0.46...
企业文件共享平台怎么选?主流方... 文件共享平台种类繁多,各有侧重。今天这篇文章,把2026年市面上主流的企业文件共享平台做个系统梳理,...
币圈院士:7.26以太坊(ET... 币圈院士:7.26以太坊(ETH)双周期指标暗藏方向,行情即将破位?最新行情分析参考 以太坊现价18...
老铺黄金发盈喜后股价跌16.2... 观点网讯:7月28日,老铺黄金股价裂口低开12.97%,最低见325.8港元,收盘报332港元,跌1...
苏泊尔上半年营收净利双降,法籍... 瑞财经 严明会 近日,苏泊尔(002032.SZ)披露2026年半年度业绩快报。 公告显示,公司上半...
IPO雷达|陕西瑞科回复二轮问... 深圳商报·读创客户端记者 梁佳彤 7月27日,据北交所官网,陕西瑞科新材料股份有限公司(下称“陕西瑞...
普京签令,俄军扩编 据新华社报道,俄罗斯总统普京27日签署命令, 决定组建几支军事建筑工程部队,并将俄武装力量编制总人数...
2027年德国杜塞尔多夫国际铸... 展会名称:2027年德国杜塞尔多夫国际铸造、冶金、热处理及铸件展览会GMTN 开始时间:2027-0...
郑州有了温通刮痧培训示范基地 本报讯(记者 杨振东 通讯员 张丹婧)温通刮痧是中医外治法里的一种,简单说就是在传统刮痧基础上,结合...
整箱茅台和单瓶茅台,回收行情为... 不少天津藏友存在疑惑:同样年份、同样品相的飞天茅台,整箱装和拆箱单瓶的回收报价存在差距,不清楚背后的...
北京五粮液收购需要遵循哪些通用... 北京五粮液收购的行业背景 近年来高端白酒的收藏与流通市场规模稳步扩张,北京作为国内重要的消费城市,五...
微软CEO重磅警告:只依赖一家... 来源:环球网 【环球网科技综合报道】7月28日消息,据外媒TechCrunch报道,微软CEO萨提亚...
策略师:金价夏季维持4000美... 汇通财经APP讯——今夏金价大概率在4000美元/盎司附近震荡筑底,市场等待美联储货币政策清晰指引。...
大众叙事下白酒行业周期如何拆解... 白酒行业的波动往往并非单纯由供需关系决定,而是 宏观经济预期与 渠道库存周期共振的结果。在大众认知中...
沈皓南:黄金低位大区间运行,短... 大家好,我是沈皓南,差不多有一个月没有更新黄金文章了,这段时间我去了美丽的新疆,自驾了独库公路,观赏...
原创 上... 2000年9月28日傍晚,济青高速临淄出口边一家小饭馆的木门被推开,六个山东汉子鱼贯而入。几个小时前...