SpringMVC
SpringMVC固定配置
-
springmvc-servlet.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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" 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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理--> <context:component-scan base-package="com.lcy.controller"/> <!--让SpringMVC不处理静态资源 .css .js .html .mp3 .mp4.... --> <mvc:default-servlet-handler/> <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping来完成映射关系 要想使@RequestMapping注解生效 必须向上下文注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理 而annotation-driven配置帮助我们自动完成上述两个实例的注入 --> <mvc:annotation-driven/> <!--视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--Json处理乱码数据--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="failOnEmptyBeans" value="false"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> </beans>
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--DispatchServlet核心分发器--> <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:springmvc-servlet.xml</param-value> </init-param> <!--启动顺序,数字越小,启动越早 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--乱码过滤 --> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
1. 什么是MVC
模型:Model(Dao/Service)
视图:view (jsp/html)
控制器:Controller(Servlet)
- 是一种软件设计规范
- 将业务逻辑,数据,显示分离的方法来组织代码
- MVC作用是降低了视图与业务逻辑间的双向耦合
- MVC是一种架构模式
2 vo实体类(UserVo)
扩展:vo是实体类的一个细分,当我一个User类有20个字段,但我只需要做一个登陆功能,前端只需要用户名和密码,这个时候可以拆分出一个vo实体类,过滤一些不必要的东西。
3 SpringMVC框架要做哪些事情
1.将url映射到Java类或Java类的方法java
2.封装用户的提交数据
3.处理请求----调用相关的业务处理----封装响应数据
4.将响应的数据进行渲染.jsp/html等表示层数据
4 SpringMVC的特点
- 轻量级,简单易学
- 高效,基于请求响应的MVC框架
- 与spring兼容性好,无缝结合
- 约定大于配置
- 功能强大:RESTful,数据验证,格式化,本地化,主题等
- 简洁灵活
5 配置SpringMVC原理版
1.配置web.xml 注册DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.配置web.xml 注册DispatcherServlet -->
<servlet>
<servlet-name>srpingmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:spring-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<!-- / 匹配所有的请求,不包括.jsp -->
<!-- /* 匹配所有的请求,包括.jsp -->
<servlet-mapping>
<servlet-name>srpingmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.编写SpringMVC的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
</web-app>
3.添加处理映射器
<!--添加处理映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
4.添加处理器适配器
<!--添加处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
5.添加视图解析器
<!-- 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
6.编写业务操作Controller,要么实现Controller接口,要么增加注解,需要返回一个ModelAndView,封装数据,视图
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放到ModelAndView中
mv.addObject("msg","HelloSpringMvc");
//封装要跳转的视图,放到ModelAndView中
mv.setViewName("hello"); //:/WEB-INF/jsp/hello.jsp
return mv;
}
}
6.分析SpringMVC的执行流程
1.DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,
DispatchedServlet接收请求并拦截请求。
-
我们假设请求的url为:http://localhost:8080/SpringMVC/hello
-
如上url拆分成三部分:
-
http://localhost:8080 指的是服务器域名
-
SpringMVC 是指部署在服务器上的web站点
-
hello 表示控制器
-
如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
2.HandlerMapping为处理器映射,DispatcherServlet调用它,HandlerMapping根据请求URL去查找Handler(处理器)
3.HandlerExecution表示具体的Handler,作用是根据URL查找控制器,如上URL
被查找控制器为(hello)
4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器等。
5.HanderlAdapter表示处理器适配器,其按照特定的规则去执行Handeler(hello请求)
6.Handler让具体的Controller执行
7.Controller将具体的执行信息返回给HanderAdapter,如ModelView(存的数据及要跳转的页面)
8.HandlerAdapter将视图逻辑名和模型传递给DispatcherServlet。(ModelView)
9.DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
- 获取了Model的数据
- 解析了View的视图名字
- 拼接前缀后缀视图名字,找到对应的视图 /WEB-INF/jsp/hello.jsp
- 将数据渲染到这个视图上
10.视图解析器将解析的逻辑视图名传给DispatcherServlet
11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
12.最终视图呈现给用户
5.RestFul风格
- 使用了RestFul风格
//RestFul:http://localhost:8080/mvc/add/a/b
@RequestMapping("/add/{a}/{b}")
public String text01(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg","结果是:"+res);
return "addPage";
}
-
没有使用RestFul
//原来的:http://localhost:8080/mvc/add?a=1&b=2 @RequestMapping("/add") public String text01(int a, int b, Model model) { int res = a + b; model.addAttribute("msg","结果是:"+res); return "addPage"; }
-
使用指定的方式 地址请求栏默认都是HTTP GET
// @RequestMapping(value = "/add/{a}/{name}",method = RequestMethod.GET) @PostMapping("/add/{a}/{name}") public String text01(@PathVariable int a, @PathVariable String name, Model model) { String res = name +a; model.addAttribute("msg","结果1是:"+res); return "addPage"; }
-
简洁:风格简单
-
安全:隐藏了程序里面的一些东西,比如参数等
-
高效:支持缓存
6.提交的注意事项
1.提交的域名称和处理方法的参数名不一样。
这个数据要从前端接收的加上@RequestParam注解,避免很多无用的请求。高效
//2.提交的域名称和处理方法的参数名不一样
@GetMapping("/t1")
public String test01(@RequestParam("username")String name, Model model) {
//1.接收前端参数
System.out.println("前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
//3.跳转视图
return "hello";
}
2.提交的是一个对象
要求前端传递的参数名和对象名必须一致,否则就是null
-
实体类
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private int age; }
-
控制层
http://localhost:8080/mvc/user/t2?name=lcy&id=1&age=15
//提交是一个对象 @GetMapping("/t2") public String test02(User user) { //1.接收前端参数 System.out.println(user); //3.跳转视图 return "hello"; }
3.数据显示到前端
- 通过ModelAndView
public class ControllerTest01 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","hello world");
mv.setViewName("test");
return mv;
}
}
-
通过Model
@RequestMapping("/hello") public String hello(Model model) { //封装数据 向模式中添加msg与值,可以注解在JSP页面取出并渲染 model.addAttribute("msg","Hello,SpringMVCAnnotation"); return "hello"; //会被视图解析器处理 }
-
ModelMap
@GetMapping("/t3")
public String test3(@RequestParam("username") String name, ModelMap map) {
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
map.addAttribute("msg",name);
return "addPage";
}
-
对比
Model 只有几个方法,适合用于存储数据,简化了新手对Model对象的操作和理解 ModelMap 继承了LinkMap,除了实现自身的一些方法,有LinkeMap的方法和特性 ModelAndView 可以在存储数据的同时,可以设置返回的逻辑视图,进行控制展示层的跳转
7.乱码问题
1.可能请求有问题,post请求换成get
<form action="${pageContext.request.contextPath}/e/t1" method="get">
<input type="text" name="username">
<input type="submit" value="提交">
</form>
2.自己创建过滤器
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//转换成HttpServletRequest HttpServletResponse
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.lcy.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
3.SpringMVC自带的过滤器
<!--配置SpringMVC的乱码过滤 -->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.修改Tomcat配置文件:设置编码!
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URLEncoding="UTF-8"/>
8.JSON
1.json是什么?
一种轻量级的数据交换格式,提高网络传输效率,简洁和清晰的结构层次
前后端分离时代
后端部署后端,提供接口,数据
JSON
前端独立部署,负责渲染后端的数据
2.JSON与JavaScript的互相转换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//编写一个JavaScript对象
var user = {
name:"陈平安",
age:18,
sex:"男"
};
//将js对象转换为JSON对象
var json = JSON.stringify(user);
console.log(json);
//将JSON对象转换为JavaScript对象
var obj = JSON.parse(json);
console.log(obj);
</script>
</head>
<body>
</body>
</html>
3.Controller返回JSON数据
3.1.jackson
-
导入jackson的jar包
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency>
-
未封装版
@RestController //整个类不会走视图解析器 public class UserController { //jackson ObjectMapper ObjectMapper mapper = new ObjectMapper(); @RequestMapping("/j1") //返回一个对象 //@ResponseBody 就不会走视图解析器,会直接返回一个字符串 public String json1() throws JsonProcessingException { //创建一个对象 User user = new User("陈平安",3,"男"); String stu = mapper.writeValueAsString(user); return stu; } @RequestMapping("/j2") //返回集合 public String json2() throws JsonProcessingException { ArrayList<User> userList = new ArrayList<>(); User user1 = new User("陈平安1", 4, "男"); User user2 = new User("陈平安2", 4, "男"); User user3 = new User("陈平安3", 4, "男"); User user4 = new User("陈平安4", 4, "男"); userList.add(user1); userList.add(user2); userList.add(user3); userList.add(user4); String str = mapper.writeValueAsString(userList); return str; } @RequestMapping("/j3") //返回时间对象 public String json3() throws JsonProcessingException { //关闭时间戳的方式 // mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false); Date date = new Date(); //自定义日期的格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //ObjectMapper,时间解析后的默认格式为:Timestamp时间戳 return mapper.writeValueAsString(sdf.format(date)); } }
-
封装版
-
utils
public class JsonUtils { public static String getJson(Object object,String dateFormat) { ObjectMapper mapper = new ObjectMapper(); //关闭时间戳的方式 mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false); //自定义日期的格式 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); mapper.setDateFormat(sdf); try { return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } public static String getJson(Object object){ return getJson(object,"yyyy-MM-dd HH:mm:ss"); } }
-
控制层
@RestController //整个类不会走视图解析器 public class UserController { //jackson ObjectMapper ObjectMapper mapper = new ObjectMapper(); @RequestMapping("/j1") //返回一个对象 //@ResponseBody 就不会走视图解析器,会直接返回一个字符串 public String json1() throws JsonProcessingException { //创建一个对象 User user = new User("陈平安",3,"男"); return JsonUtils.getJson(user); } @RequestMapping("/j2") //返回集合 public String json2() throws JsonProcessingException { ArrayList<User> userList = new ArrayList<>(); User user1 = new User("陈平安1", 4, "男"); User user2 = new User("陈平安2", 4, "男"); User user3 = new User("陈平安3", 4, "男"); User user4 = new User("陈平安4", 4, "男"); userList.add(user1); userList.add(user2); userList.add(user3); userList.add(user4); return JsonUtils.getJson(userList); } @RequestMapping("/j3") //返回时间对象 public String json3() throws JsonProcessingException { Date date = new Date(); return JsonUtils.getJson(date,"yyyy-MM-dd HH:mm:ss"); } }
-
3.2 FastJson
-
导入FastJson的jar包
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.68</version> </dependency>
-
转换JSON格式
@RequestMapping("/j4") public String json4() throws JsonProcessingException { ArrayList<User> userList = new ArrayList<>(); User user1 = new User("陈平安1", 4, "男"); User user2 = new User("陈平安2", 4, "男"); User user3 = new User("陈平安3", 4, "男"); User user4 = new User("陈平安4", 4, "男"); userList.add(user1); userList.add(user2); userList.add(user3); userList.add(user4); System.out.println("=============java对象转JSON字符串======="); String str1 = JSON.toJSONString(userList); System.out.println("JSON.toJSONString(List)=====>"+str1); String str2 = JSON.toJSONString(user1); System.out.println("JSON.toJSONString(user1)=====>"+str2); System.out.println("=============JSON字符串转Java对象======="); User user = JSON.parseObject(str2, User.class); System.out.println("JSON.parseObject(str2, User.class)=====>"+user); System.out.println("===========Java对象转JSON对象========="); JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2); System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name")); System.out.println("=========JSON对象转Java对象=========="); User toJavaObject = JSON.toJavaObject(jsonObject1, User.class); System.out.println("JSON.toJavaObject(jsonObject1, User.class)====>"+toJavaObject); return str1; }
4.代码优化
-
JSON乱码统一解决
<!--Json处理乱码数据--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="failOnEmptyBeans" value="false"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
9.Ajax技术
1.什么是Ajax
-
异步的JavaScript和XMl
-
在无需重新加载整个网页的情况下,更新部门网页的技术
2.Ajax使用
2.1 示例1
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> <script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.0.js"></script> <script> function a() { $.post({ url:"${pageContext.request.contextPath}/t2", data:{"name":$("#username").val()}, success:function (data,status) { console.log("data="+data); console.log("status="+status); //状态码 } }) } </script> </head> <body> <!--失去焦点的时候,发起一个请求到后台 --> <input type="text" id="username" οnblur="a()"> </body> </html>
-
控制层
@RestController public class AjaxController { @RequestMapping("/t2") public void test2(String name, HttpServletResponse resp) throws IOException { System.out.println("接收了:"+name); if ("lcy".equals(name)) { resp.getWriter().print("true"); }else { resp.getWriter().print("flase"); } } }
2.2 示例2
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.0.js"></script> <script> $(function () { $("#btn").click(function () { /* $.post(url,param[可以省略],success) */ $.post("${pageContext.request.contextPath}/t3",function (data) { console.log(data); var html =""; for (let i = 0; i < data.length; i++) { html += "<tr>"+ "<td>"+data[i].name+"</td>"+ "<td>"+data[i].age+"</td>" + "<td>"+data[i].sex+"</td>" + "</tr>" } $("#content").html(html); }) }) }); </script> </head> <body> <input type="button" value="加载数据" id="btn"> <table> <tr> <td>name</td> <td>age</td> <td>sex</td> </tr> <tbody id="content"> <%-- 数据:后台--%> </tbody> </table> </body> </html>
-
控制器
@RequestMapping("/t3") public List<User> test3() { ArrayList<User> userList = new ArrayList<>(); //添加数据 userList.add(new User("java",1,"男")); userList.add(new User("前端",1,"女")); userList.add(new User("运维",1,"男")); return userList; }
2.3 登陆验证Ajax
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script src="${pageContext.request.contextPath}/statics/js/jquery-3.4.0.js"></script> <script> function a1() { $.ajax({ url:"${pageContext.request.contextPath}/t5", data:{"username":$("#name").val()}, success:function (data) { if (data.toString()=="ok"){ $("#userInfo").css("color","green").html(data); }else { $("#userInfo").css("color","red").html(data); } } }) } function a2() { $.ajax({ url: "${pageContext.request.contextPath}/t5", data: {"password":$("#pwd").val()}, success:function (data) { if (data.toString()=="ok"){ $("#pwdInfo").css("color","green").html(data); }else { $("#pwdInfo").css("color","red").html(data); } } }) } </script> </head> <body> <p> 用户名:<input type="text" id="name" onblur="a1()"> <span id="userInfo"></span> </p> <p> 密码:<input type="text" id="pwd" onblur="a2()"> <span id="pwdInfo"></span> </p> </body> </html>
-
控制层
@RequestParam的require 默认是true
@RequestMapping("/t5") public String a4(@RequestParam(required = false,value = "username") String name,@RequestParam(required = false,value = "password") String pwd) { String msg = ""; if (name != null) { if ("admin".equals(name)) { System.out.println(name); msg = "ok"; }else { msg = "用户名有误"; } } if (pwd != null) { if ("123".equals(pwd)) { System.out.println(pwd); msg = "ok"; }else { msg = "密码错误"; } } return msg; }
10.SpringMVC:拦截器
1.过滤器和拦截器的区别
-
拦截器是AOP思想的具体应用
-
过滤器任何JavaWeb过程都可以使用
-
url-pattern中配置了/*之后,对所有要访问的资源进行拦截
-
拦截器是SpringMVC的工程才能使用
-
只会拦截访问的控制器方法,jsp/html/css…是不会拦截的
2.登陆验证拦截
-
控制层
@Controller @RequestMapping("/user") public class LoginController { @RequestMapping("/login") //登陆 public String login(HttpSession session, String username, String password) { //把用户信息存在session中 session.setAttribute("userLoginInfo",username); return "main"; } @RequestMapping("/main") public String main() { return "main"; } @RequestMapping("/goLogin") public String login() { return "login"; } @RequestMapping("/goOut") @ResponseBody public String out(HttpSession session, HttpServletResponse response) throws IOException { session.removeAttribute("userLoginInfo"); response.sendRedirect("/mvc_06/"); return "redirect:/user/index"; } }
-
登陆页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登陆</title> </head> <body> <!--在Web-inf下面的所有页面资源,只能通过Controller,或者servlet访问 --> <h1>登陆页面</h1> <form action="${pageContext.request.contextPath}/user/login" method="post"> 用户名:<input type="text" name="username"/> 密码:<input type="text" name="password"/> <input type="submit" value="提交"> </form> </body> </html>
-
初始页 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <a href="${pageContext.request.contextPath}/user/goLogin">登陆页面</a> <a href="${pageContext.request.contextPath}/user/main">首页</a> </body> </html>
-
首页 main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>首页</title> </head> <body> <h1>首页</h1> <p>用户名:${userLoginInfo}</p> <a href="${pageContext.request.contextPath}/user/goOut">注销</a> </body> </html>
-
spring-mvc.xml配置
<!--拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!--/user/**表示user下面的所有请求都会经过这个拦截器 --> <mvc:mapping path="/user/**"/> <bean class="com.lcy.config.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors>
-
拦截器配置
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//登陆页面也会放行
if (request.getRequestURI().contains("goLogin")) {
return true;
}
if (request.getRequestURI().contains("login")) {
return true;
}
//放行:判断什么情况下登陆
if (session.getAttribute("userLoginInfo") != null) {
return true;
}
//判断什么情况下是没有登陆的
request.getRequestDispatcher("/web/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
11.SpringMVC:上传下载
1.文件上传
设置了enctype=“multipart/form-data”,浏览器会采用二进制流的方式来处理表单数据。
-
导入jar包、
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!-- 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>
-
配置spring-mvc.xml id必须为multipartResolver
<!--文件上传配置 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--请求编码的格式必须和jsp的pageEncoding属性一致,以便正确读取表单的内容,默认ISO-8859-1 --> <property name="defaultEncoding" value="utf-8"/> <!--上传文件大小上限,单位为字节(10485760=10M) --> <property name="maxUploadSize" value="10485760"/> <property name="maxInMemorySize" value="40960"/> </bean>
-
控制层(两种方法)
@RestController public class FileController { //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象 //批量上传CommonsMultipartFile则为数组即可 @RequestMapping("/upload") public String fileUpload1(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException { //获取文件名 file.getOriginalFilename() String uploadFileName = file.getOriginalFilename(); //如果文件名为空,直接返回首页 if ("".equals(uploadFileName)) { return "redirect:/index.jsp"; } System.out.println("上传文件名:"+uploadFileName); //上传路径保存设置 UUID 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 os = new FileOutputStream(new File(realPath, uploadFileName));//文件输出流 //读取写出 int len =0; byte[] buffer = new byte[1024]; while ((len=is.read(buffer))!=-1){ os.write(buffer,0,len); os.flush(); } os.close(); is.close(); return "redirect:/index.jsp"; } @RequestMapping("/upload2") public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException { //上传路径保存设置 String path = request.getServletContext().getRealPath("/upload"); File realPath = new File(path); if (!realPath.exists()){ realPath.mkdir(); } //上传文件地址 System.out.println("上传文件保存地址:"+realPath); //通过CommonsMultipartFile的方法直接写文件 file.transferTo(new File(realPath+"/"+file.getOriginalFilename())); return "redirect:/index.jsp"; } }
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <!--enctype="multipart/form-data"以二进制流的格式传输 --> <form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post"> <input type="file" name="file"> <input type="submit" value="upload"> </form> </body> </html>
2.文件下载(其他配置与文件下载一致)
- 控制层
@RequestMapping("/download")
public String downloads(HttpServletResponse response,HttpServletRequest request) throws Exception {
String name = request.getParameter("download");
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = name;
//1.设置响应头
response.reset(); //设置页面不缓存,清空buffer
response.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);
//2.读取文件----输入流
FileInputStream input = new FileInputStream(file);
//3.写出文件-----输出流
ServletOutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index = 0;
//4.执行写出操作
while ((index = input.read(buff))!= -1){
out.write(buff,0,index);
out.flush();
}
out.close();
input.close();
return"ok";
}
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>下载</title> </head> <body> <form action="${pageContext.request.contextPath}/download" method="post"> 你要下载的:<input type="text" name="download"> <input type="submit" value="提交"> </form> </body> </html>
ing downloads(HttpServletResponse response,HttpServletRequest request) throws Exception {
String name = request.getParameter(“download”);
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = name;
//1.设置响应头
response.reset(); //设置页面不缓存,清空buffer
response.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);
//2.读取文件----输入流
FileInputStream input = new FileInputStream(file);
//3.写出文件-----输出流
ServletOutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index = 0;
//4.执行写出操作
while ((index = input.read(buff))!= -1){
out.write(buff,0,index);
out.flush();
}
out.close();
input.close();
return"ok";
}
* jsp页面
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>下载</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/download" method="post">
你要下载的:<input type="text" name="download">
<input type="submit" value="提交">
</form>
</body>
</html>