SpringMVC是对Servlet的深层次封装,其架构功能分工明确,注解强大易用,方便整合MyBatis,Hiberate,JPA等其他框架。
友情提示:阅读本文前需具备一些javaweb相关知识,可参考以下博文进行了解:
搭建一个简单的MVC框架_刚上路DE小白的博客-CSDN博客_mvc框架怎么建立
Spring入门之框架核心----IOC/AOP_刚上路DE小白的博客-CSDN博客
首先了解MVC模式:
Model-View-Controller:模型--视图--控制器
Model: 模型层 javaBean 负责数据访问和业务处理 dao service pojo
View: 视图 JSP技术 负责收集和展示数据
Controller: 控制器 servlet技术 中间调度
控制器的工作:
1、接受客户端的请求(包括请求中携带的数据)
2、处理请求:调用后台的模型层中的业务逻辑
3、页面导航:处理完毕给出响应:JSP页面
下面代码示例为一个简单的SpringMVC案例,不涉及dao层,主要了解SpringMVC的工作机制和如何使用。
1.首先创建一个项目:
创建maven项目后按照如下图补全目录结构:
2.在pom文件中添加依赖:
4.0.0
com.lxj
MySpringMVC
1.0-SNAPSHOT
8
8
war
org.springframework
spring-webmvc
5.2.13.RELEASE
javax.servlet
javax.servlet-api
4.0.1
provided
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core
jackson-databind
2.9.0
commons-fileupload
commons-fileupload
1.3.1
org.apache.maven.plugins
maven-compiler-plugin
3.8.0
1.8
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
/
8080
3.创建配置文件:
首先是Spring的配置文件,在resources文件夹下创建applicationContext.xml:
然后是SpringMVC的配置文件SpringMVC.xml(注意注释中对相关细节有说明):
注意:我们的项目中将存在两个容器,一个是 Spring 容器,另一个是SpringMVC 容器,Spring 容器通过 ContextLoaderListener 来加载,SpringMVC 容器则通过DispatcherServlet 来加载,这两个容器不一样:
4.通过web.xml对spring和springmvc配置:
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springMVC.xml
1
dispatcherServlet
/
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
characterEncodingFilter
/*
httpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
httpMethodFilter
/*
至此,相关配置文件创建完成,这里对SprngMVC工作流程做简要分析:
新建一个实体类:
package com.lxj.pojo.com.lxj;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class Team {
private Integer teamId;
private String teamName;
private String location;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createTime;
@Override
public String toString() {
return "Team{" +
"teamId=" + teamId +
", teamName='" + teamName + '\'' +
", location='" + location + '\'' +
", createTime=" + createTime +
'}';
}
public Integer getTeamId() {
return teamId;
}
public void setTeamId(Integer teamId) {
this.teamId = teamId;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
新建hello.jsp页面:
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/5
Time: 21:49
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Hello
8、获取集合类型的参数
7、获取数组类型的参数
6、获取日期类型的参数
5、直接使用URL地址传参
4、使用HttpServletRequest 对象获取参数
3、请求参数和方法名称的参数不一致
2、使用对象接收多个参数
1、直接使用方法的参数逐个接收
新建对应的controlor:
package com.lxj.controller;
import com.lxj.pojo.com.lxj.QueryVO;
import com.lxj.pojo.com.lxj.Team;
import com.lxj.service.TeamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Controller
@RequestMapping("param")
public class TeamController {
@Autowired
TeamService teamService;
/**
* 1、直接使用方法的参数逐个接收:方法的参数名称必须与用户请求中携带的参数名称保持一致,否则
就获取不到
* 好处:不需要类型转换
*/
@RequestMapping("test01")
public ModelAndView test01(Integer teamId,String teamName,String
teamLocation){
System.out.println("test01-----------------");
System.out.println(teamId);
System.out.println(teamName);
System.out.println(teamLocation);
return new ModelAndView("ok");
}
//2、使用对象接收多个参数:要求用户请求中携带的参数名称必须是实体类中的属性保持一致,否则就获取不到
@RequestMapping("test02")
public ModelAndView test02(Team team){
System.out.println("test02-----------------");
System.out.println(team);
return new ModelAndView("ok");
}
//3、请求参数和方法名称的参数不一致:使用@RequestParam进行矫正,
// value属性表示请求中的参数名称
// required属性表示参数是否是必须的:true:必须赋值,否则报出400错;false:可以不赋值,结果就是null
@RequestMapping("test03")
public ModelAndView test03(@RequestParam(value = "teamId",required = false)
Integer id,
@RequestParam(value = "teamName",required = true)
String name,
@RequestParam("location") String loc){
System.out.println("test03-----------------");
System.out.println(id);
System.out.println(name);
System.out.println(loc);
return new ModelAndView("ok");
}
//4、使用HttpServletRequest 对象获取参数:跟原来的javaWeb项目中使用的方式是一样的
@RequestMapping("test04")
public ModelAndView test04(HttpServletRequest request){
System.out.println("test04-----------------");
String teamId = request.getParameter("teamId");
String teamName = request.getParameter("teamName");
String location = request.getParameter("location");
if(teamId!=null)
System.out.println(Integer.valueOf(teamId));
System.out.println(teamName);
System.out.println(location);
return new ModelAndView("ok");
}
//5、直接使用URL地址传参: 借助@PathVariable 注解
// 例如http://localhost:8080/param/test05/1001/lacker/las
@RequestMapping("test05/{id}/{name}/{loc}")
public ModelAndView test05(@PathVariable("id") Integer teamId,
@PathVariable("name") String teamName,
@PathVariable("loc") String teamLocation){
System.out.println("test05-----------------");
System.out.println(teamId);
System.out.println(teamName);
System.out.println(teamLocation);
return new ModelAndView("ok");
}
//6、获取日期类型的参数
@RequestMapping("test06")
public ModelAndView test06(Team team){
System.out.println("test06-----------------");
System.out.println(team);
return new ModelAndView("ok");
}
//7、获取数组类型的参数
@RequestMapping("test07")
public ModelAndView test07(String[] teamName,HttpServletRequest request){
System.out.println("test07-----------------");
//方式1:
for (String s : teamName) {
System.out.println(s);
} System.out.println("---------------");
//方式2:
String[] teamNames = request.getParameterValues("teamName");
for (String name : teamNames) {
System.out.println(name);
}
return new ModelAndView("ok");
}
//8、获取集合类型的参数: 简单类型的可以通过@RequestParam注解实现;对象集合不支持直接获取,必须封装在类中,作为一个属性操作
@RequestMapping("test08")
public ModelAndView test08(@RequestParam("teamName") List nameList){
System.out.println("test08-----------------");
for (String s : nameList) {
System.out.println(s);
}
return new ModelAndView("ok");
}
@RequestMapping("test09")
public ModelAndView test09(QueryVO vo){
System.out.println("test09-----------------");
for (Team team : vo.getTeamList()) {
System.out.println(team);
}
return new ModelAndView("ok");
}
@RequestMapping("Hello.do")
public ModelAndView add(){
System.out.println("TeamController:add()");
teamService.add();
ModelAndView mv=new ModelAndView();
mv.addObject("teamName","湖人");//相当于request.setAttrubuite("teanName","湖人");
mv.setViewName("index");//未来经过springmvc的视图解析器处理,转换成物理资源路径,相当于request.getRequestDispatcher("index.jsp").forward();
//经过InternalResourceViewResolver对象的处理之后加上前后缀就变为了/jsp/index.jsp
return mv;
}
}
遇到中午乱码问题,可在web.xml中添加字符集过滤器(详见上文web.xml中)
新建result.jsp:
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/6
Time: 20:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
result
result----------------
test01------${teamName}---
test02---request作用域获取:---${requestScope.team.teamName}--
-${requestScope.team.teamId}---${requestScope.team.location}
test02---session作用域获取:---${sessionScope.team.teamName}--
-${sessionScope.team.teamId}---${sessionScope.team.location}
ajax请求自定义对象的结果展示
ajax请求自定义对象的结果展示
ajax请求Map的结果展示
新建对应的controllor:
package com.lxj.controller;
import com.lxj.pojo.com.lxj.Team;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
@Controller
@RequestMapping("result")
public class ResultController {
//1、返回值是ModelAndView: 这种方式既有数据的携带还有资源的跳转,可以选择该种方式
@RequestMapping("test01")
public ModelAndView test01(){
ModelAndView mv=new ModelAndView();//模型与视图
//携带数据
mv.addObject("teamName","湖人队");//相当于request.setAttribute("teamName","湖人队“);
mv.setViewName("result");// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
return mv;
}
//2、返回字符串
@RequestMapping("test02")
public String test02(HttpServletRequest request){
Team team=new Team();
team.setLocation("迈阿密");
team.setTeamId(1002);
team.setTeamName("热火");
//携带数据
request.setAttribute("team",team);
request.getSession().setAttribute("team",team);
//资源的跳转
return "result";// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
}
//3、返回对象类型:Integer Double String 自定义类型 List Map 返回的不是逻辑视图的名称,而直接就是数据返回 ,一般是ajax请求搭配使用 ,将json格式的数据直接返回给响应体一定要与@ResponseBody
@ResponseBody
@RequestMapping("test03-1")
public Integer test031(){
return 666;
}
@ResponseBody
@RequestMapping("test03-2")
public String test032(){
return "test";
}
@ResponseBody
@RequestMapping("test03-3")
public Team test033(){
Team team=new Team();
team.setLocation("迈阿密");
team.setTeamId(1002);
team.setTeamName("热火");
return team;
}
@ResponseBody
@RequestMapping("test03-4")
public List test034(){
List list=new ArrayList<>(5);
for(int i=1;i<=5;i++) {
Team team = new Team();
team.setLocation("迈阿密"+i);
team.setTeamId(1002+i);
team.setTeamName("热火"+i);
list.add(team);
}
return list;
}
@ResponseBody
@RequestMapping("test03-5")
public Map test035(){
Map map=new HashMap();
for(int i=1;i<=5;i++) {
Team team = new Team();
team.setLocation("金州"+i);team.setTeamId(1000+i);
team.setTeamName("勇士"+i);
//日期类型,在返回的时候是个数字,如果想要按日期格式展示需要在实体类对应属性添加注解@JsonFormat(pattern = "yyyy-MM-dd")
team.setCreateTime(new Date());
map.put(team.getTeamId()+"",team);
}
return map;
}
//通过 HttpServletRequest 做服务端跳转
@RequestMapping("test04-1")
public void test041(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("直接使用HttpServletRequest进行服务器端的转发");
request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
}
//通过 HttpServletResponse 做重定向
@RequestMapping("test04-2")
public void test042(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("直接使用HttpServletResponse重定向跳转");
response.sendRedirect("/jsp/ok.jsp");
}
//通过 HttpServletResponse 给出响应
@RequestMapping("test04-3")
public void test043(HttpServletResponse response) throws ServletException,
IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("返回void类型测试---直接返回字符串");
writer.flush();
writer.close();
}
//也可以自己手动指定响应头去实现重定向:
@RequestMapping("test04-4")
public void test044(HttpServletResponse response) throws ServletException,
IOException {
response.setStatus(302);//设置响应码,302表示重定向
response.setHeader("Location","/jsp/ok.jsp");
}
}
package com.lxj.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("navigation")
public class NavigationController {
@RequestMapping("test01-1")
public String test011(HttpServletRequest request){
request.setAttribute("teamName","湖人");
//return "ok";//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径
return "forward:/jsp/ok.jsp";//当添加了forward前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
}
@RequestMapping("test01-2")
public ModelAndView test012(){
ModelAndView mv=new ModelAndView();
mv.addObject("teamName","热火");
//mv.setViewName("ok");//默认方式:由视图解析器处理之后将逻辑视图转为物理资源路径
mv.setViewName( "forward:/jsp/ok.jsp");//当添加了forward前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
return mv;
}
@RequestMapping("test02-1")
public String test021(HttpServletRequest request){
request.setAttribute("teamName","勇士");//页面上无法获取到存储在request作用域中的值,请求中断了
return "redirect:/jsp/ok.jsp";//当添加了redirect前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
}
@RequestMapping("test02-2")
public ModelAndView test022(){
ModelAndView mv=new ModelAndView();
mv.addObject("teamName","huangfeng");
//存储在request作用域中的值以参数的形式追加在URL后面
http://localhost:8080/jsp/ok.jsp?teamName=huangfeng&teamId=1002
mv.addObject("teamId","1002");
mv.setViewName( "redirect:/jsp/ok.jsp");//当添加了redirect前缀之后,视图解析器中的前后缀就失效了,必须自己编写绝对路径
return mv;
}
}
首先自定义不同级别的异常类:
package com.lxj.exception;
public class TeamException extends Exception{
public TeamException() {
}
public TeamException(String message) {
super(message);
}
}
package com.lxj.exception;
public class TeamIdException extends TeamException{
public TeamIdException() {
}
public TeamIdException(String message) {
super(message);
}
}
package com.lxj.exception;
public class TeamNameException extends TeamException{
public TeamNameException() {
}
public TeamNameException(String message) {
super(message);
}
}
编写对应的controller:
package com.lxj.controller;
import com.lxj.exception.TeamIdException;
import com.lxj.exception.TeamNameException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("exp")
public class ExController {
@RequestMapping("test01/{id}/{name}")
public ModelAndView test01(@PathVariable("id") Integer teamId, @PathVariable("name") String teamName)
throws TeamIdException,TeamNameException {
ModelAndView mv=new ModelAndView();
if(teamId<=1000){
throw new TeamIdException("teamId不合法!必须在1000之上!");
}
if("test".equals(teamName)){
throw new TeamNameException("teamName不合法!不能使用test!");
}
System.out.println(10/0);
mv.setViewName("ok");
return mv;
}
@ExceptionHandler(value = {TeamIdException.class,TeamNameException.class,Exception.class})
public ModelAndView exHandler(Exception ex){
ModelAndView mv=new ModelAndView();
mv.addObject("msg",ex.getMessage());
if(ex instanceof TeamIdException)
mv.setViewName("idError");
else if(ex instanceof TeamNameException)
mv.setViewName("nameError");
else
mv.setViewName("error");
return mv;
}
}
package com.lxj.exception;
import com.lxj.exception.TeamException;
import com.lxj.exception.TeamIdException;
import com.lxj.exception.TeamNameException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = TeamIdException.class)
public ModelAndView exHandler1(Exception ex){
ModelAndView mv=new ModelAndView();
mv.addObject("msg",ex.getMessage());
mv.setViewName("idError");
return mv;
}
@ExceptionHandler(value = TeamNameException.class)
public ModelAndView exHandler2(Exception ex){
ModelAndView mv=new ModelAndView();
mv.addObject("msg",ex.getMessage());
mv.setViewName("nameError");
return mv;
}
@ExceptionHandler(value = TeamException.class)
public ModelAndView exHandler4(Exception ex){
ModelAndView mv=new ModelAndView();
mv.addObject("msg",ex.getMessage());
mv.setViewName("nameError");
return mv;
}
@ExceptionHandler(value = Exception.class)
public ModelAndView exHandler3(Exception ex){
ModelAndView mv=new ModelAndView();
mv.addObject("msg",ex.getMessage());
mv.setViewName("error");
return mv;
}
}
分别写error.jsp/iderror.jsp/nameerror.jsp进行实验:
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/13
Time: 20:40
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
error
默认的错误页面--${msg}
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/13
Time: 20:40
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
teamId
teamId Error----${msg}
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/13
Time: 20:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
teamName
teamName error---${msg}
SpringMVC 中的 拦截器( Interceptor)是非常重要的,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。拦截的时间点在“处理器映射器HandlerMapping根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器HandlerAdaptor执行处理器之前”。在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链HandlerExecutionChain,并返回给了前端控制器。自定义拦截器,需要实现 HandlerInterceptor 接口。而该接口中含有三个方法:
preHandle(request,response, Object handler):
该方法在处理器方法执行之前执行。其返回值为boolean,若为true,则紧接着会执行处理器方法,且会将afterCompletion()方法放入到一个专门的方法栈中等待执行。
postHandle(request,response, Object handler,modelAndView):
该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。
afterCompletion(request,response, Object handler, Exception ex):
当 preHandle()方法返回true时,会将该方法放到专门的方法栈中,等到对请求进行响应的所工作完成之后才执行该方法。即该方法是在前端控制器渲染(数据填充)了响应页面之后执行的,此时对ModelAndView再操作也对响应。
首先自定义拦截器:
package com.lxj.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 {
//执行时间: 控制器方法执行之前,在ModelAndView返回之前
//使用场景: 登录验证
// 返回值 true : 继续执行控制器方法 表示放行 false: 不会继续执行控制器方法,表示拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle---------------------");
return true;
}
//执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
//使用场景: 日记记录,记录登录的ip,时间
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle---------------------");
}
//执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
//使用场景: 全局资源的一些操作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion----------------------");
}
}
package com.lxj.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 MyInterceptor2 implements HandlerInterceptor {
//执行时间: 控制器方法执行之前,在ModelAndView返回之前
//使用场景: 登录验证
// 返回值 true : 继续执行控制器方法 表示放行 false: 不会继续执行控制器方法,表示拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle2---------------------");
return true;
}
//执行时间: 控制器方法执行之hou后,在ModelAndView返回之前,有机会修改返回值
//使用场景: 日记记录,记录登录的ip,时间
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle2---------------------");
}
//执行时间: 控制器方法执行之后,在ModelAndView返回之后,没有机会修改返回值
//使用场景: 全局资源的一些操作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion2----------------------");
}
}
然后在springmvc.xm中进行配置(详见前文配置文件)
首先添加依赖,并在springmvc.xml中配置
commons-fileupload
commons-fileupload
1.3.1
在项目中添加文件夹保存上传的文件:
添加fileHandle.jsp文件:
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/14
Time: 21:04
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
文件操作
新建controller:
package com.lxj.controller;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.UUID;
@Controller
@RequestMapping("file")
public class FileController {
@RequestMapping("upload")
public String upload(@RequestParam("myFile") MultipartFile myFile,
HttpServletRequest request){
//获取文件的原始名称 d:\te.aa\txcat.jpg
String originalFilename = myFile.getOriginalFilename();
// 实际开发中,一般都要将文件重新名称进行存储
// 存储到服务器的文件名称=随机的字符串+根据实际名称获取到源文件的后缀
String fileName= UUID.randomUUID().toString().replace("-","")
+originalFilename.substring(originalFilename.lastIndexOf("."));
System.out.println(fileName);
//文件存储路径
String realPath = request.getServletContext().getRealPath("/uploadFile")+"/";
try {
myFile.transferTo(new File(realPath+fileName));//真正的文件上传到服务器指定的位置
System.out.println("上传成功!"+realPath+fileName);
} catch (IOException e) {
e.printStackTrace();
}
return "ok";
}
@RequestMapping("download")
public ResponseEntity download(HttpServletRequest request) throws IOException {
String path=request.getServletContext().getRealPath("/uploadFile")+"/9078a8f8d2f148629136f3f03133631e.png";
//创建响应 的头信息的对象
HttpHeaders headers=new HttpHeaders();
//标记以流的方式作出响应
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//以附件的形式响应给用户
headers.setContentDispositionFormData("attachment", URLEncoder.encode("9078a8f8d2f148629136f3f03133631e.png","utf-8"));
File file=new File(path);
ResponseEntity resp=new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
return resp;
}
@RequestMapping("hello")
public String hello(){
return "fileHandle";
}
}
文件过滤器:
package com.lxj.interceptor;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;
public class FileInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean flag=true;
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map fileMap = multipartRequest.getFileMap();
//遍历文件
Iterator iterator = fileMap.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
MultipartFile file = multipartRequest.getFile(key);
String originalFilename = file.getOriginalFilename();
String hz = originalFilename.substring(originalFilename.lastIndexOf("."));
//判断后缀是否合法
if (!hz.toLowerCase().equals(".png") && !hz.toLowerCase().equals(".jpg")) {
request.getRequestDispatcher("/jsp/fileTypeError.jsp").forward(request, response);
flag = false;
}
}
}
return flag;
}
}
不强制,但强烈建议。
主要是用GET、POST、PUT、DELETE。他们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
创建restful.jsp:
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2022/6/6
Time: 20:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
result
result----------------
test01------${teamName}---
test02---request作用域获取:---${requestScope.team.teamName}--
-${requestScope.team.teamId}---${requestScope.team.location}
test02---session作用域获取:---${sessionScope.team.teamName}--
-${sessionScope.team.teamId}---${sessionScope.team.location}
ajax请求自定义对象的结果展示
ajax请求自定义对象的结果展示
ajax请求Map的结果展示
这里需要注意:在Ajax中,采用Restful风格PUT和DELETE请求传递参数无效,传递到后台的参数值为null,前端页面中的ajax发送请求的时候在url中加 &_method=”PUT” 或者 &_method=”DELETE” 即可。
自己封装一个公用的响应结果实体类:
package com.lxj.pojo.com.lxj;
import java.util.List;
public class AjaxResultVo {
private Integer code;
private String msg;
private List list;
private T obj;
public AjaxResultVo(){
code=200;
msg="ok";
list=null;
obj=null;
}
public AjaxResultVo(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public AjaxResultVo(Integer code, String msg, List list) {
this.code = code;
this.msg = msg;
this.list = list;
}
public AjaxResultVo(Integer code, String msg, T obj) {
this.code = code;
this.msg = msg;
this.obj = obj;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
新建控制器:
package com.lxj.controller;
import com.lxj.pojo.com.lxj.Team;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
@Controller
@RequestMapping("result")
public class ResultController {
//1、返回值是ModelAndView: 这种方式既有数据的携带还有资源的跳转,可以选择该种方式
@RequestMapping("test01")
public ModelAndView test01(){
ModelAndView mv=new ModelAndView();//模型与视图
//携带数据
mv.addObject("teamName","湖人队");//相当于request.setAttribute("teamName","湖人队“);
mv.setViewName("result");// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
return mv;
}
//2、返回字符串
@RequestMapping("test02")
public String test02(HttpServletRequest request){
Team team=new Team();
team.setLocation("迈阿密");
team.setTeamId(1002);
team.setTeamName("热火");
//携带数据
request.setAttribute("team",team);
request.getSession().setAttribute("team",team);
//资源的跳转
return "result";// 经过视图解析器InternalResourceViewResolver的处理,将逻辑视图名称加上前后缀变为物理资源路径 /jsp/result.jsp
}
//3、返回对象类型:Integer Double String 自定义类型 List Map 返回的不是逻辑视图的名称,而直接就是数据返回 ,一般是ajax请求搭配使用 ,将json格式的数据直接返回给响应体一定要与@ResponseBody
@ResponseBody
@RequestMapping("test03-1")
public Integer test031(){
return 666;
}
@ResponseBody
@RequestMapping("test03-2")
public String test032(){
return "test";
}
@ResponseBody
@RequestMapping("test03-3")
public Team test033(){
Team team=new Team();
team.setLocation("迈阿密");
team.setTeamId(1002);
team.setTeamName("热火");
return team;
}
@ResponseBody
@RequestMapping("test03-4")
public List test034(){
List list=new ArrayList<>(5);
for(int i=1;i<=5;i++) {
Team team = new Team();
team.setLocation("迈阿密"+i);
team.setTeamId(1002+i);
team.setTeamName("热火"+i);
list.add(team);
}
return list;
}
@ResponseBody
@RequestMapping("test03-5")
public Map test035(){
Map map=new HashMap();
for(int i=1;i<=5;i++) {
Team team = new Team();
team.setLocation("金州"+i);team.setTeamId(1000+i);
team.setTeamName("勇士"+i);
//日期类型,在返回的时候是个数字,如果想要按日期格式展示需要在实体类对应属性添加注解@JsonFormat(pattern = "yyyy-MM-dd")
team.setCreateTime(new Date());
map.put(team.getTeamId()+"",team);
}
return map;
}
//通过 HttpServletRequest 做服务端跳转
@RequestMapping("test04-1")
public void test041(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("直接使用HttpServletRequest进行服务器端的转发");
request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response);
}
//通过 HttpServletResponse 做重定向
@RequestMapping("test04-2")
public void test042(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
System.out.println("直接使用HttpServletResponse重定向跳转");
response.sendRedirect("/jsp/ok.jsp");
}
//通过 HttpServletResponse 给出响应
@RequestMapping("test04-3")
public void test043(HttpServletResponse response) throws ServletException,
IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("返回void类型测试---直接返回字符串");
writer.flush();
writer.close();
}
//也可以自己手动指定响应头去实现重定向:
@RequestMapping("test04-4")
public void test044(HttpServletResponse response) throws ServletException,
IOException {
response.setStatus(302);//设置响应码,302表示重定向
response.setHeader("Location","/jsp/ok.jsp");
}
}
本文是学习了 “开课吧JAVAEE开发工程师” 课程相关内容后结合课堂笔记和代码总结的,如有意愿和兴趣进行更全面的学习和提升可参加开课吧相关课程培训学习:JavaEE商业项目架构就业班-开课吧