SpringMVC(二)
响应数据和结果视图
-
返回值分类:
- 字符串
- void
- ModelAndView 对象:是 spring 提供的一个对象,可以用来调整具体的 JSP 视图
@RequestMapping("testModelAndView") public ModelAndView testModelAndView(){ //创建 ModelAndView 对象 ModelAndView mv = new ModelAndView(); System.out.println("testModelAndView执行了……"); // 模拟从数据库中查询出User对象 User user = new User(); user.setUsername("jljl"); user.setPassword("456"); user.setAge(22); //把 user 对象存储到 mv 对象中,也会把 user 对象存入到 request 对象 mv.addObject("user",user); //跳转到哪个页面,ModelAndView会找到视图解析器,找到其对应的目录下的页面 mv.setViewName("success"); return mv; }
-
SpringMVC 框架提供的 转发 和 重定向
/** * 使用关键字的方式进行转发或者重定向 * @return */ @RequestMapping("testForwardOrRedict") public String testForwardOrRedict(){ System.out.println("testForwardOrRedict执行了……"); //请求的转发 //return "forward:/WEB-INF/pages/success.jsp"; //重定向 return "redirect:/index.jsp"; }
-
ResponseBody 响应 json 数据
- 过滤静态资源:由于web.xml中配置前端控制器时设置了拦截所有资源,导致jsp页面无法加载到JQuery文件,所以要进行这样的设置。
<!--前端控制器,哪些静态资源不拦截--> <mvc:resources location="/js/" mapping="/js/**"/> <!--新的设置方式,可以设置不拦截所有静态资源--> <!--<mvc:default-servlet-handler/>-->
- 发送 ajax 请求
<script src="${pageContext.request.contextPath}/js/jquery-3.1.1.min.js"></script> <script> //页面加载,绑定单击事件 $(function () { $("#btn").click(function () { //发送ajax请求 $.ajax({ url:"${pageContext.request.contextPath}/user/testAjax", contentType:"application/json;charset=utf-8", data:'{"username":"jinlu","password":"123","age":22}', dataType:"json", type:"post", success:function (data) { //data:服务器响应的 json 数据,进行解析 } }); }); }); </script>
<button id="btn">发送 ajax 请求</button>
/** * 模拟异步请求响应 */ @RequestMapping("testAjax") public void testAjax(@RequestBody String body){ System.out.println("testAjax执行了……"); System.out.println(body); }
-
响应 json 数据格式
- json 字符串和 JavaBean 对象互相转换过程中,需要使用 jackson 的 jar 包
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
- response.jsp
<script> //页面加载,绑定单击事件 $(function () { $("#btn").click(function () { //alert("hello btn"); //发送ajax请求 $.ajax({ url:"${pageContext.request.contextPath}/user/testAjax", contentType:"application/json;charset=utf-8", data:'{"username":"jinlu","password":"123","age":22}', dataType:"json", type:"post", success:function (data) { //data:服务器响应的 json 数据,进行解析 alert(data); alert(data.username); alert(data.password); alert(data.age); } }); }); }); </script>
- UserController.java
@RequestMapping("testAjax") public @ResponseBody User testAjax(@RequestBody User user){ System.out.println("testAjax执行了……"); //客户端发送ajax请求,传的是json字符串,后端把json字符串封装到user对象 System.out.println(user); //做响应,模拟查询数据库 user.setUsername("LULU"); user.setAge(40); //做响应 return user; }
springMVC实现文件上传
- 传统文件上传
<!--传统方法文件上传的jar包-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<form action="user/fileUpload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" /><br/>
<input type="submit" value="上传"/>
</form>
@RequestMapping("/fileUpload1")
public String fileUpload1(HttpServletRequest request) throws Exception {
System.out.println("fileUpload1执行了……");
//使用fileupload组件完成文件上传
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads");
//判断,该路径是否存在
File file = new File(path);
if (!file.exists()){
//创建该文件夹
file.mkdirs();
}
//解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory(); //磁盘文件
ServletFileUpload upload = new ServletFileUpload(factory);
//解析request
List<FileItem> items = upload.parseRequest(request);
//遍历
for (FileItem item: items) {
//进行判断,当前item对象是否是上传文件项
if (item.isFormField()){
//说明是普通表单项
}else{
//说明是上传文件项
//获取上传文件的名称
String filename = item.getName();
//把文件名称设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//完成上传文件
item.write(new File(path,filename));
//删除临时文件(>10kb会删掉,<10kb内存会保存临时文件,所以要删除掉)
item.delete();
}
}
return "success";
}
- SpringMVC 文件上传
<!--配置文件解析器,id 必须为"multipartResolver"-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--文件最大大小-->
<property name="maxUploadSize" value="10485760"/>
</bean>
/**
* SpringMVC 文件上传
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/fileUpload2")
public String fileUpload2(HttpServletRequest request, MultipartFile upload) throws IOException {
System.out.println("fileUpload2执行了……");
//上传的位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断路径是否存在
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
//获取上传文件的名称
String filename = upload.getOriginalFilename();
//设置唯一值,uuid
String uuid = UUID.randomUUID().toString().replace("-","");
filename = uuid + "_" + filename;
//完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
-
springMVC 跨服务器方式文件上传
- 分服务器的目的
- 应用服务器:负责部署到我们的应用。
- 数据库服务器:运行我们的数据库。
- 缓存和消息服务器:负责处理大并发访问的缓存和消息。
- 文件服务器:负责存储用户上传文件的服务器。
依赖注入:
<!--SpringMVC跨服务器方式上传文件依赖的包--> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
后台控制:
/** * 跨服务器文件上传 * @param upload * @return * @throws IOException */ @RequestMapping("/fileUpload3") public String fileUpload3(MultipartFile upload) throws IOException { System.out.println("fileUpload3执行了……"); //定义上传文件服务器路径 String path = "http://localhost:9990/uploads/"; //说明上传文件项 //获取上传文件的名称 String filename = upload.getOriginalFilename(); //设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-",""); filename = uuid + "_" + filename; //完成文件上传,跨服务器文件上传 //1.创建客户端对象 Client client = Client.create(); //2.和图片服务器进行连接 WebResource webResource = client.resource(path + filename); //3.上传文件 webResource.put(upload.getBytes()); return "success"; }
上传失败,出现错误
HTTP Status 500 - Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:9090/uploads/69f070620aa54e2f97a2c62299e02d14_1715-9.jpg returned a response status of 403 Forbidden
原因是跨服务器上传文件,但是文件不能写入,需要在 tomcat 目录下conf文件夹下的 web.xml 的
<servlet>
配置中加入:<init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param>
- 分服务器的目的
springMVC中的异常处理
- 自定义异常类
/**
* 自定义异常类
*/
public class SysException extends Exception {
//存储提示信息
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
- 异常处理器:必须实现
HandlerExceptionResolver
/**
* 异常处理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常业务逻辑
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Nullable
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @Nullable Object o, Exception e) {
//获取异常对象
SysException sysException = null;
if (e instanceof SysException){
sysException = (SysException) e;
}else {
sysException = new SysException("系统正在维护……");
}
//创建ModelAndView 对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",sysException.getMessage());
mv.setViewName("error");
return mv;
}
}
- 配置异常处理器
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="com.ssm.exception.SysExceptionResolver"/>
- 测试:
@RequestMapping("/testException")
public String testException() throws SysException {
System.out.println("testException执行了...");
try {
//模拟异常
int i = 10/0;
} catch (Exception e) {
//打印异常信息
e.printStackTrace();
//抛出自定义异常信息
throw new SysException("查询所有用户信息出错……");
}
return "success";
}
springMVC中的拦截器
-
拦截器类似于Servlet 中的过滤器 Filter,用于对处理器进行预处理和后处理。
-
拦截器 & 过滤器
- 过滤器是servlet 规范中的一部分,任何 Javaweb 工程都可以使用。
- 拦截器是springMVC自己的,只有使用了springMVC框架的工程才能使用。
- 过滤器在url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
- 拦截器只会拦截访问的控制器方法,如果访问的是jsp、html、css、image或者 js 是不会进行拦截的。
-
流程:
- 编写拦截器类,实现
HandlerInterceptor
接口
public class MyInterceptor implements HandlerInterceptor { /** * 预处理,controller方法执行前 * return true 放行,执行下一拦截器,如果没有,执行controller中的方法 * return false 不放行 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor执行了..."); return true; } /** * 后处理方法 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor执行了...后"); // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * success.jsp执行之后才会执行 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("MyInterceptor执行了...最后"); } }
- 配置拦截器
<mvc:interceptors> <mvc:interceptor> <!--要拦截的具体方法--> <mvc:mapping path="/user/*"/> <!--不要拦截的方法--> <!--<mvc:exclude-mapping path=""/>--> <!--配置拦截器对象--> <bean class="com.ssm.interceptor.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
- 编写拦截器类,实现