一、响应数据以及结果视图
昨天从原理图中得到一个结论—只需要编写处理器以及页面即可。
编写一个方法就是一个处理器,昨天的关注点在如何获取数据上。
编写一个方法,这个方法到底有多少种返回值类型。
1、String类型
返回string类型表示需要跳转的页面的路径以及页面名称。是需要走视图解析器。<br /> 如果我们返回String类型,我们的数据应该如何传递?可以传递数据
@RequestMapping("/view02")
public String view02(Model model){
model.addAttribute("name","李四");
return "b";
}
以上返回String类型的值其实是将Model 和 View 拆分开了,当我们需要给页面传递值得时候,我们就定义个Model model,如果不需要给页面传递值,只需要跳转页面,就不定义Model 即可,使用起来更加的灵活,所以可以替代ModelAndView
2、void类型
总结:
1) 每一个处理器中的方法,除了基本数据类型,String类型以及实体类型还有集合之外,还可以传递req以及resp
request以及response这两个变量可以只出现一个,也可以出现两个,也可以都不出现。
如果项目中使用到了该对象,需要导入servlet-api以及jsp的jar包
<!--加这两个的目的是HttpServletRequest Response这两个类-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
2) 返回是void 类型,我们可以通过req中的内部转发的方式跳转页面,但是该方式跳转的页面不走视图解析器
@RequestMapping("/show01")
public void show01(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入show01");
// 该页面正确访问,说明req内部转发的url是不经过视图解析器的
req.getRequestDispatcher("a.jsp").forward(req,resp);
}
@RequestMapping("/show02")
public void show02(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入show02");
// b页面不能正常访问,说明此方式不走视图解析器
req.getRequestDispatcher("b").forward(req,resp);
}
3)返回值是void类型,跳转页面也可以通过resp的重定向的方式,也是不走视图解析器,但是无法访问WEB-INF下的资源
3、返回值类型是ModelAndView
ModelAndView 其实就是一个类,里面可以通过方法存放数据以及视图名字,走视图解析器,并且页面可以通过el表达式获取数据
@Controller
public class Demo02Controller {
@RequestMapping("/view01")
public ModelAndView view01(){
ModelAndView modelAndView = new ModelAndView();
// 在该对象中,填充数据以及视图
modelAndView.addObject("name","张三");
modelAndView.setViewName("b");
return modelAndView;
}
}
二、重定向和内部转发
通过以上案例我们基本知道SpringMVC中如何进行重定向和内部转发,但是以上做法有一些不足:
我们需要引入HttpServletRequest以及Response对象,还需要引入jar包,而且编写代码也比较繁琐,Spring帮助我们升级了重定向和内部转发的写法。
总结:
springmvc帮助我们简化了重定向和内部转发的写法,无需req和resp对象,也不需要导入jar包
写法:
重定向: “redirect:/路径” , 不可以访问WEB-INF下的内容
内部转发: “forward:/路径” 可以访问WEB-INF下的内容
@Controller
public class Demo03Controller {
@RequestMapping("/showPage01")
public String showPage(){
// springmvc的重定向,起作用了,说明此种方法进行重定向是没有问题的
return "redirect:/a.jsp";
}
@RequestMapping("/showPage02")
public String showPage2(){
// springmvc的重定向,没有访问到资源,说明这种重定向的方式也是无法访问web-inf下的资源的
return "redirect:/WEB-INF/page/b.jsp";
}
@RequestMapping("/showPage03")
public String showPage3(){
// springmvc的内部转发,起作用了,说明内部转发没有问题,而且也说明内部转发可以访问web-inf下的资源
return "forward:/WEB-INF/page/b.jsp";
}
@RequestMapping("/showPage04")
public String showPage4(){
// springmvc的内部转发,起作用了,说明内部转发没有问题
return "forward:/a.jsp";
}
}
三、通过ResponseBody 响应 Json数据(响应Ajax请求)
1、编写一个页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用ajax完成登录功能</title>
<script src="${pageContext.request.contextPath}/js/jquery-1.8.3.min.js"></script>
<script>
function ajaxLogin(){
var userName= $("#username").val();
var password= $("#password").val();
$.post("${pageContext.request.contextPath}/login",{"name":userName,"password":password},function(data){
alert(data);
});
return false;//阻止事件冒泡== 让原来的button不提交表单
}
</script>
</head>
<body>
用户名:<input id="username" type="text" name="username"/><br/>
密码:<input id="password" type="password" name="password"/><br/>
<input type="button" value="登录" onclick="return ajaxLogin()"/>
</body>
</html>
2、编写需要响应的controller
@Controller
public class LoginController {
@RequestMapping("/login")
@ResponseBody// 不走视图解析器,如果是String,直接返回,如果是实体,将实体数据变为json数据
public String login(String name,String password){
if(name.equals("laoyan")&&password.equals("root")){
return "success";
}else{
return "fail";
}
}
}
3、当你需要引入一些静态资源的时候有两种写法
在springmvc中
<!--当我们需要引入一些静态资源的时候,springmvc中的前端控制器,会拦截我们的静态资源,需要放行-->
<!-- 一个指的是url一个指的是文件夹 -->
<mvc:resources mapping="/js/**" location="/js/"/>
<!--<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/img/**" location="/img/"/>-->
第二种:
<!--放行所有静态资源,如果写这一个,上面的就不用写了,二选一-->
<mvc:default-servlet-handler/>
总结:
@ResponseBody
两个作用
第一个作用:让返回值不走视图解析器
第二个作用:将数据变为json数据,如果是String,原样输出,不是json,如果是实体,会自动变为json数据
如果我们将返回值从String 变为 Result实体,出现了异常
html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> No converter found for return value of type: class com.qfedu.pojo.Result</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.qfedu.pojo.Result
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:221)
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:182)
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
出现以上的异常,是说Result实体无法转换为json数据,从而失败了。
package com.qfedu.pojo;
public class Result {
private int code; // 0 表示成功, 1 表示用户名错误 2 表示密码错误 3 表示验证码错误 4 表示没有权限
private String message;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
需要导入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>
</dependencies>
重点:如果返回值是一个实体类型,一定记得导入三个jackson的jar包
四、文件上传
使用springmvc自带的工具完成文件上传。
第一步:准备页面
必须是post请求,必须是多段式表单 enctype=”multipart/form-data”,必须有一个 file 输入框
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传演示</title>
</head>
<body>
<!--每个表单都有一个类型,默认的类型 application/x-www-form-urlencoded-->
<form action="${pageContext.request.contextPath}/uploadImg" method="post" enctype="multipart/form-data">
请上传您的帅照:<input type="file" name="imageFile"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
第二步:编写Controller
@Controller
public class UploadController {
@RequestMapping("/uploadImg")
public String upload(MultipartFile imageFile) throws IOException {
File file = new File("C:/a.jpg");
imageFile.transferTo(file);
return "success";// 跳转到success页面
}
}
第三步:需要导入文件上传需要的jar包
<!--文件上传所需的两个jar包-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
第四步:需要配置文件上传解析器 springmvc.xml中
<!--此处的id必须等于multipartResolver 否则报错 配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<!--设置文件上传最大的大小 5M-->
<value>5242880</value>
</property>
</bean>
测试代码!
发现没有任何问题,图片上传成功!
修改版之后的文件上传!
@RequestMapping("/uploadImg")
public String upload(MultipartFile imageFile) throws IOException {
// 动态获取后缀名
String originalFilename = imageFile.getOriginalFilename();
// aaaa.png
// 获取到字符串中,最后一个. 的下标位置
int index = originalFilename.lastIndexOf(".");
// 从某个坐标开始截取,截取到最后,返回一个新的字符串
String suffix=originalFilename.substring(index);
// 获取一个新的文件名字
String fileName = UUIDUtils.getUUID()+suffix;
File file = new File("C:/"+fileName);
imageFile.transferTo(file);
return "success";// 跳转到success页面
}
五、通过tomcat搭建一个图片服务器
如何指定某个文件夹是tomcat的一个项目呢?
1、修改server.xml文件
在最后面的Hosts标签内,填写一个
docBase 存放你要存放的图片的文件夹 path 就是将来浏览器访问时候的虚拟路径名
2、修改该tomcat下的三个端口号。
3、一定要创建好文件夹
4、找一个图片,放进去,启动tomcat,通过浏览器访问
http://localhost:8081/images/a.jpg
六、springmvc的一个跨域上传
A Tomcat 跑的是java代码 —上传到—> B Tomcat 下
跨域访问: 百度去访问淘宝
localhost:80/xxxx/ 项目 localhost:8081/images/
IP地址,域名,以及端口只要有一个不一致,就叫跨域。
第一步:导入jar包
<!--处理跨域上传图片所需要的jar-->
<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>
第二步:编写controller方法
// 跨域上传图片
@RequestMapping("/uploadImg2")
public String upload2(MultipartFile imageFile) throws IOException {
// 动态获取后缀名
String originalFilename = imageFile.getOriginalFilename();
// aaaa.png
// 获取到字符串中,最后一个. 的下标位置
int index = originalFilename.lastIndexOf(".");
// 从某个坐标开始截取,截取到最后,返回一个新的字符串
String suffix=originalFilename.substring(index);
// 获取一个新的文件名字
String fileName = UUIDUtils.getUUID()+suffix;
// 创建客户端
Client client = Client.create();
String path="http://localhost:8081/images/";
//和图片服务器进行连接
WebResource resource = client.resource(path + fileName);
// 图片上传
resource.put(imageFile.getBytes());
return "success";// 跳转到success页面
}
第三步:一定要修改tomcat图片服务器中的配置文件 在tomcat的 web.xml 中添加如下配置
因为默认的tomcat是不允许别人跨域访问资源的,所以需要如下配置才能解决