基于原生html form表单实现办法
<form action=34;${pageContext.request.contextPath}/user" method="post"> id:<input name="id" type="text" /> ${errors.id}<br /> <input type="submit" value="提交" /></form>
package com.demo.controllers.entity;import jakarta.validation.constraints.Min;import jakarta.validation.constraints.NotNull;import lombok.Data;@Datapublic class User { @NotNull @Min(1) private Integer id;}
package com.demo.controllers;import com.demo.controllers.entity.User;import jakarta.validation.Valid;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.annotation.PostMapping;import java.util.HashMap;import java.util.List;import java.util.Map;/ 在须要验证的javaBean的属性上面加入对应的验证表明 在须要验证的处理方法的对应javaBean参数上加上@Valid 在须要验证的处理方法参数中加入BindingResult,代表自己处理缺点,这样就不会显示缺点页面了 将缺点信息循环通过map存入到request域中 在jsp通过${errors.id}获取对应的缺点信息 /@Controllerpublic class UserController { @PostMapping("/user") public String add(@Valid User user, BindingResult result, Model model) { // 将缺点信息取出来,输出到jsp页面 // 判断当前是否涌现了缺点 if(result.hasErrors()) { // 存放缺点信息,有利于在jsp等分别取出缺点信息 Map<String, String> errors = new HashMap<>(); // key: 缺点信息的属性名,value: 缺点信息 // 获取所有的缺点信息 包含 缺点的属性,缺点信息 List<FieldError> fieldErrors = result.getFieldErrors(); for (FieldError fieldError : fieldErrors) { errors.put(fieldError.getField(), fieldError.getDefaultMessage()); } model.addAttribute("errors", errors); //如果验证失落败将要求转发到添加页面 return "user/add"; } System.out.println(user); return "show"; }}
基于Spring form标签库的实现办法(静态数据)
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %><html><head> <title>添加用户</title></head><body> <h1>添加用户</h1><%-- Spring的form标签库method是支持put和delete--%> <form:form action="${pageContext.request.contextPath}/spring/user" method="post" modelAttribute="user"> id: <form:input path="id"></form:input><form:errors path="id"></form:errors> </form:form></body></html>
/ 在jsp中导入spring-form标签库 在form标签上一定要加上modelAttribute 加上对应的form标签,必须都要以<form:开头 @param user @param result @param model @return /@PostMapping("/form/user")public String springformAdd(@Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { return "user/add"; } System.out.println(user); return "show";}/ 添加一个显示jsp的处理方法,一定要传入一个空的User到model中 @param user @return /@GetMapping("/user/add")public String addView(User user) { return "user/add";}
基于Spring form标签库的实现办法(动态数据)
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %><html><head> <title>添加用户</title></head><body> <h1>添加用户</h1> <form:form action="${pageContext.request.contextPath}/spring/user" method="post" modelAttribute="user"> hobbies: <%--静态数据源--%> <form:checkbox path="hobbies" value="唱歌"></form:checkbox> <form:label path="hobbies">唱歌</form:label> <form:checkbox path="hobbies" value="舞蹈"></form:checkbox> <form:label path="hobbies">舞蹈</form:label> <br> <%--动态数据源--%> <form:checkboxes path="hobbies" items="${list}"></form:checkboxes> <select> <option value="1">北京</option> <option value="2">上海</option> </select> </form:form></body></html>
/ 初始化页面的数据 调用其它的方法之前,都要调用此方法 / @ModelAttribute public void initData(Model model) { // 初始化数据 List<String> list = Arrays.asList("唱歌", "舞蹈"); model.addAttribute("list", list);// Map<String, String> map = new HashMap<>();// map.put("1", "唱歌");// map.put("2", "舞蹈");//// model.addAttribute("list", map); } / 在jsp中导入spring-form标签库 在form标签上一定要加上modelAttribute 加上对应的form标签,必须都要以<form:开头 @param user @param result @return / @PostMapping("/form/user") public String springformAdd(@Valid User user, BindingResult result) { if (result.hasErrors()) { return "user/add"; } System.out.println(user); return "show"; } / 添加一个显示jsp的处理方法,一定要传入一个空的User到model中 @param user @return / @GetMapping("/user/add") public String addView(User user) { return "user/add"; }
JSON处理
java转换为json的过程:序列化
json转换为java的过程:反序列化
json要用双引号,不能用单引号
JAVA
JSON
String
"string"
Integer
111
JavaBean/Map
{"id":1, "name":"zhangsan"}
数组/凑集
String[]/List<String>
["a","b","c"]
List<User>
List<Map>
[
{"id":1, "name":"zhangsan"},
{"id":2, "name":"wangwu"},
...
]
User:
属性:id,name, Role role
{"id":1, "name":"zhangsan","role":{"id":2, "name":"wangwu"}}
User:
属性:id,name,List<Role>
{"id":1, "name":"zhangsan","role":[{"id":2, "name":"wangwu"},
{"id":3, "name":"lisi"}
,...]
}
RestController掌握器类中所有的处理方法都会以json的数据进行相应,相称于掌握器类中所有的处理方法都加上了@ResponseBody
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.14.2</version></dependency><dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.14.2</version></dependency><dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.14.2</version></dependency>
package com.demo.controllers.entity;import com.fasterxml.jackson.annotation.JsonFormat;import com.fasterxml.jackson.annotation.JsonIgnore;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.Date;@Data@NoArgsConstructor@AllArgsConstructorpublic class User { private Integer id; private String usernae; @JsonIgnore // 当返回javaBean的json时,会忽略该属性 private String password; @JsonFormat(pattern = "yyyy-MM-dd") // 用户转换json时格式化数据 private Date birthday;}
package com.demo.controllers;import com.demo.controllers.entity.User;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.Date;@Controller@RestControllerpublic class JsonController { @RequestMapping("/json/response")// @ResponseBody // 将返回值作为文本进行返回,并不是返回视图 public User responseJson() { User user = new User(1, "zhangsan", "123456", new Date()); return user; }}
Spring MVC获取JSON数据
// 工具转化为json字符串var jsonValue = JSON.stringify(user);
@RequestBody: 要求中JSON数据转化成JAVA@ResponseBody: 相应中把JAVA转化成JSON数据Spring MVC上传|下载Servlet 下载
package com.demo.controllers;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.;import java.net.URLEncoder;/ Servlet下实现的文件下载 /@WebServlet("/download")public class DownloadServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String realPath = this.getServletContext().getRealPath("/file/1.png"); // 获取要下载的文件的绝对路径 // 将文件路径封装成File工具 File tmpFile = new File(realPath); // 获取文件名 String fileName = tmpFile.getName(); // 设置相应头 content-disposition: 设置文件下载的打开办法,默认在网页上打开 // attachment;filename因此下载办法来打开文件 resp.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); InputStream is = new FileInputStream(realPath); // 获取文件输入流 int len = 0; byte[] buffer = new byte[1024]; OutputStream out = resp.getOutputStream(); while((len = is.read(buffer)) != -1) { out.write(buffer, 0, len); // 将缓冲区的数据输出到客户端浏览器 } is.close(); }}
Spring MVC 下载
package com.demo.controllers;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;@Controllerpublic class DownloadController { @RequestMapping("/download1") public String download1(HttpServletRequest request, HttpServletResponse response) throws Exception{ String realPath = request.getServletContext().getRealPath("F:\\code\\springmv01\\web\\images\\img.png"); File tmpFile = new File(realPath); String fileName = tmpFile.getName(); response.setHeader("content-disposition", "attachment; filename = " + URLEncoder.encode(fileName, "UTF-8")); InputStream is = new FileInputStream(realPath); int len = 0; byte[] buffer = new byte[1024]; OutputStream out = response.getOutputStream(); while((len = is.read(buffer)) != -1) { out.write(buffer, 0, len); // 将缓冲区的数据输出到客户端浏览器 } is.close(); return null; } / 基于Spring ResponseEntity的文件下载 不支持缓冲区 ResponseEntity 可以定制文件的相应内容,相应头,相应状态码 @return / @RequestMapping("/getDownload") public ResponseEntity<String> getDownload() { String body = "hello world"; HttpHeaders headers = new HttpHeaders(); headers.set("Set-Cookie","name=hello"); return new ResponseEntity<>(body, headers, HttpStatus.OK); } @RequestMapping("/download2") public ResponseEntity<Byte[]> download2(HttpServletRequest request, HttpServletResponse response) throws Exception{ String realPath = request.getServletContext().getRealPath("F:\\code\\springmv01\\web\\images\\img.png"); File tmpFile = new File(realPath); String fileName = tmpFile.getName(); HttpHeaders headers = new HttpHeaders(); headers.set("content-disposition", "attachment; filename = " + URLEncoder.encode(fileName, "UTF-8")); InputStream is = new FileInputStream(realPath); return new ResponseEntity<Byte[]>(new Byte[is.available()], headers, HttpStatus.OK); }}
Spring MVC 上传
<!--文件上传解析器--><bean id= "multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8" /> <!--文件上传最大的字节数--> <property name="maxUploadSize" value="#{1024102410}" /></bean>
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/upload" method="post"> 文件描述:<input type="text" name="desc" /> <br> 文件:<input type="file" name="myfile" multiple accept="image/"/> <br> <%--multiple: 多文件上传--%> <input type="submit" value="提交" /></form>
/ 多文件文件上传 /@PostMapping("/upload")public String upload(String desc, MultipartFile[] multipartFiles) throws IOException { for (MultipartFile myfile : multipartFiles) { String path = "D:/" + myfile.getOriginalFilename(); File file = new File(path); myfile.transferTo(file); } return "success";}
/ 多线程文件上传 /@PostMapping("/upload")public String upload(String desc, MultipartFile[] multipartFiles) throws InterruptedException { for (MultipartFile myfile : multipartFiles) { Thread thread = new Thread(() -> { String path = "D:/" + myfile.getOriginalFilename(); File file = new File(path); try { myfile.transferTo(file); } catch (IOException e) { e.printStackTrace(); } }); thread.start(); thread.join(); // 让子线程实行完在实行主线程 } return "success";}
Spring MVC虚拟目录上传
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body> <%--磁盘路径--%> <img src="${pageContext.request.contextPath}/img/${filename}"></body></html>
/ 文件上传到三个路径 1. 项目路径(适宜项目小,上传利用率低 2. 磁盘路径,这种办法通过虚拟目录的映射 3. 静态资源做事器(CDN) /@PostMapping("/upload")public String upload(String desc, MultipartFile myfile, Model model) throws IOException { String path = "D:/" + myfile.getOriginalFilename(); File file = new File(path); myfile.transferTo(file); model.addAttribute("filename", myfile.getOriginalFilename()); return "success";}
Spring MVC拦截器
拦截器:采取AOP的设计思想,类似Servlet过滤器,用来拦截处理方法
如:权限验证、日志、非常记录、记录方法实行韶光
<mvc:interceptors> <bean class="com.demo.interceptors.MyInterceptor" /></mvc:interceptors>
package com.demo.interceptors;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Arrays;public class MyInterceptor implements HandlerInterceptor { / 在处理方法之前实行 @param request 在方法要求进来之前变动request中的的属性值 @param response @param handler 封装了当前处理方法的信息 @return true: 后续调用链是否实行 false:中断后续实行 @throws Exception / @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handler1 = (HandlerMethod) handler; } System.out.println("-------类:["+ handler1.getBean().getClass() +"] 方法:["+ handler1.getMethod().getName() +"] 参数:["+ Arrays.toString(handler1.getMethod().getParameters()) +"] 前实行---------preHandle--------------------------------"); return true; } / 在要求实行后实行,在视图渲染之前实行 当处理方法涌现了非常则不会实行方法 @param request @param response 在方法实行后变动response中的信息 @param handler 封装了当前处理方法的信息 @param modelAndView 封装了model和view,要求结束后可以修正model中的数据或新增model数据,也可修正view的跳转 @throws Exception / @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("------方法后实行,在视图渲染之前----------postHandle--------------------------------"); } / 在视图渲染之后实行,涌现非常也会实行该方法 @param request @param response @param handler @param ex 可以记录非常日志的功能,或者打消资源 @throws Exception / @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("-----------在视图渲染之后--------afterHandle----------"); }}
拦截器|过滤器的差异
<!--必须担保对应的要求没有映射处理--><mvc:view-controller path="/admin" view-name="admin"></mvc:view-controller><mvc:interceptors> <!--直接配置bean会拦截Spring MVC所有要求--> <bean class="com.demo.interceptors.MyInterceptor" /> <!--不是所有的要求都要拦截--> <mvc:interceptor> <!--须要拦截要求--> <mvc:mapping path="/"/> <!--不须要拦截的要求--> <mvc:exclude-mapping path="/login"/> <!--拦截器--> <bean class="com.demo.interceptors.CheckLoginInterceptor" /> </mvc:interceptor></mvc:interceptors>
package com.demo.interceptors;import org.springframework.util.StringUtils;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;/ 验证用户是否登录的拦截器 /public class CheckLoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); // 如果没有登录 if (StringUtils.isEmpty(session.getAttribute("username"))) { response.sendRedirect(request.getContextPath() + "/login"); return false; } else { return true; } }}
Spring MVC 国际化通过浏览器措辞设置国际化
<!--设置国际化支持 配置国际化属性资源文件--><bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"> <array> <value>i18n/login</value> <value>i18n/index</value> </array> </property></bean>
package com.demo.controllers;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/ 基于浏览器设置的措辞切换国际化 1. 新建jsp对应的国际化属性资源文 login_en_US.properties login_zh_CN.properties 2. 配置sping_mvc.xml 将国际化支持和资源文件都注入到springmvc中 3. 在jsp页面调用对应的属性资源内容:<spring:message code="绑定属性资源文件中对应的key" /@Controllerpublic class I8NController { @RequestMapping("/i18n") public String i18n() { return "login"; }}
通过超链接来切换国际化
》》》办法一
<!--利用SessionLocaleResolver保持Locale的状态,会在session中获取Locale工具--><bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
package com.demo.controllers;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.servlet.i18n.SessionLocaleResolver;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Locale;/ 基于浏览器设置的措辞切换国际化 1. 新建jsp对应的国际化属性资源文 login_en_US.properties login_zh_CN.properties 2. 配置sping_mvc.xml 将国际化支持和资源文件都注入到springmvc中 3. 在jsp页面调用对应的属性资源内容:<spring:message code="绑定属性资源文件中对应的key" /@Controllerpublic class I8NController { @RequestMapping("/i18n") public String i18n() { return "login"; } @RequestMapping("/i18n/{language}_{country}") public String changeLocale(@PathVariable("language") String language, @PathVariable("country") String country, HttpServletRequest request, HttpServletResponse response, @Autowired SessionLocaleResolver localeResolver) { Locale local = new Locale(language, country); localeResolver.setLocale(request, response, local); return "login"; }}
》》》办法二
<!--利用SessionLocaleResolver保持Locale的状态,会在session中获取Locale工具--><bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean><!--利用springmvc供应的拦截器,吸收local参数,设置到session中去--><mvc:interceptors> <!--所有的要求都会被拦截--> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /></mvc:interceptors>
Spring MVC基于表明的国际化Spring MVC 非常处理@ExceptionHandler
通过@ExceptionHandler可以在方法中记录日志
@ControllerAdvice是对Controller的增强全局非常处理
全局数据绑定
全局数据预处理
》》》优先级:处理器非常 > 全局非常中详细非常 > 全局非常