一、响应数据和结果视图
1.返回值类型
①返回字符串
Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器来寻找对应的页面
@RequestMapping("/stringResponse")
public String testReturnString(){
System.out.println("stringResponse");
return "success";
}
②返回值是void
如果返回值是void,会显示404错误,因为会默认将请求路径作为等同的返回字符串的值类型来处理:
@RequestMapping("/void")
public void testVoid(){
System.out.println("Void");
}
所以我们要使用手动输入跳转或重定向代码(所写的路径不会通过视图解析器):
@RequestMapping("/void")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("Void");
//请求重定向
response.sendRedirect(request.getContextPath()+"/RedirectSuccess.jsp");
//表示结束
return;
}
③返回值类型是ModelAndView
2.SpringMVC框架提供的转发和重定向
①forward请求转发
controller方法返回值为String类型,进行请求转发
/**
* 使用forward关键字进行请求转发
* "forward:转发发jsp路径",不走视图解析器,所以要编写完整路径
* @return
*/
@RequestMapping("/springMVCForward")
public String testSpringMVCForward(){
System.out.println("springMVCForward");
return "forward:/WEB-INF/pages/success.jsp";
}
②redirect请求重定向
controller犯法返回值为String类型,进行请求重定向
/**
* 使用redirect关键字进行请求重定向
* "redirect:重定向jsp路径",不走视图解析器,所以要编写完整路径
* @return
*/
@RequestMapping("/springMVCRedirect")
public String testSpringMVCRedirect(){
System.out.println("springMVCRedirect");
return "redirect:/RedirectSuccess.jsp";
}
3.ResponseBody响应json数据
第一步,导入一个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>
第二步,在页面编写一个ajax请求:
所以要解决一个静态资源访问的问题,因为前端控制器会拦截所以资源导致如css、js、img等资源无法被访问,所以要在springmvc.xml文件中配置,使得资源不被拦截:
使用mvc:resource标签配置不过滤
1.location属性表示webapp目录下的包下所有文件
2.mapping属性表示/静态资源开头的所有请求路径,如/静态资源/a文件或/静态资源/a文件夹/b文件
<!--设置静态资源访问-->
<!-- js代码 -->
<mvc:resources mapping="/js/**" location="/js/"/>
编写的ajax请求如下(注意data中的格式必须使用单引号保住,中间数据问json字符串格式):
<script src="js/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$("#btn").click(function () {
$.ajax({
url:"response/ajaxTest",
contentType:"application/json;charset=utf-8",
type:"post",
data:'{"username":"lazy","password":"123"}',
dataType:"json",
success:function (data) {
alert(data);
}
})
})
})
</script>
使用@RequestBody注解将json数据封装为JavaBean:
@RequestMapping("ajaxTest")
public void testAjax(@RequestBody User user){
System.out.println(user);
System.out.println("ajaxTest");
}
使用@ResponseBody注解将JavaBean对象封装为json数据发送到客户端:
@RequestMapping("ajaxTest")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println(user);
System.out.println("ajaxTest");
user.setUsername("哈哈");
return user;
}
二、使用springMVC完成文件上传
1.传统文件上传
先编写一个文件上传的页面(其中的name属性一定要编写,否则文件无法上传),
<form action="file/traditionalMethod" method="post" enctype="multipart/form-data">
选择上传文件:<input type="file" name="upload"/><br/>
<input type="submit" value="上传"/>
</form>
后台代码如下:
@Controller
@RequestMapping("/file")
public class FileUploadController {
@RequestMapping("/traditionalMethod")
public String testTraMethod(HttpServletRequest request) throws Exception {
//获取要上传到的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
System.out.println(path);
//创建File对象,作为等下文件下载的位置
File file = new File(path);
//判断路径是否存在,不存在就创建
if(!file.exists()){
file.mkdir();
}
//创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
//解决乱码问题
servletFileUpload.setHeaderEncoding("utf-8");
//解析request对象
List<FileItem> fileItems = servletFileUpload.parseRequest(request);
System.out.println(fileItems);
for(FileItem item:fileItems){
if (item.isFormField()){
}else{
//获取文件名称
String filename = item.getName();
String uuid = UUID.randomUUID().toString().replace("-", "");
filename = uuid + "_" + filename;
//上传文件
item.write(new File(file, filename));
//清除临时文件
item.delete();
}
}
return "success";
}
}
2.springMVC文件上传
第一点,SpringMVC框架提供了MultipartFile对象,该对象表示要上传的文件,要求变量名称必须与表单file标签的name属性相同,
@RequestMapping("/springMVCMethod")
public String testSpringMVCMethod(HttpServletRequest request,MultipartFile upload) throws IOException {
System.out.println("springMVC");
//获取要上传到的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
//创建File对象,作为等下文件下载的位置
File target = new File(path);
//判断路径是否存在,不存在就创建
if(!target.exists()){
target.mkdir();
}
//获取文件名称
String fileName = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid + "_" + fileName;
//上传文件
upload.transferTo(new File(target, fileName));
return "success";
}
同时要配置一个文件解析器,
<!--配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"></property>
<property name="defaultEncoding" value="utf-8"></property>
</bean>
3.SpringMVC跨服务器文件上传
第一步,搭建一个文件服务器
第二步,编写jsp页面
<form action="file/fileServer" method="post" enctype="multipart/form-data">
选择上传文件:<input type="file" name="upload"/><br/>
<input type="submit" value="上传"/>
</form>
第三步,编写springMVC服务器后台代码
@RequestMapping("/fileServer")
public String testFileServer(MultipartFile upload) throws IOException {
System.out.println("fileServer");
//获取服务器路径
String path = "http://localhost:9090/file_server/uploads/";
//获取文件名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase() ;
//文件名唯一化
filename = uuid + "_" + filename;
//开启客户端
Client client = Client.create();
//连接到服务器获取内存资源
WebResource resource = client.resource(path + filename);
//将文件上传到服务器
String encode = URLEncoder.encode(new String(upload.getBytes()), "utf-8");
resource.put(encode.getBytes());
return "success";
}
在自己复习的时候发现编写的后台代码,无法成实现,有无大佬知道如何解决,错误代码如下
三、SpringMVC异常处理
第一步,自定义异常类(可有可无)
public class MyException extends Exception {
private static final long serialVersionUID = 4055945147128016300L; // 异常提示信息
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public MyException(String message) {
this.message = message;
}
}
第二步,定义异常处理器
/**
* 跳转到错误页面
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
MyException myException = null;
//获取异常
if(e instanceof MyException){
myException = (MyException) e;
}else {
myException = new MyException("请练习管理员");
}
//存入异常信息到request域中
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("errorMsg",myException.getMessage());
//设置跳转页面
modelAndView.setViewName("error");
return modelAndView;
}
第三步,配置异常处理器
<!-- 配置异常处理器 -->
<bean id="myHandler" class="com.lazy.exception_handler.MyHandler" ></bean>
四、SpringMVC中的拦截器
1.拦截器概述
-
SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
-
可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链
中的拦截器会按着定义的顺序执行。
-
拦截器和过滤器的功能比较类似,有区别
- 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
- 拦截器是SpringMVC框架独有的。
- 过滤器配置了/*,可以拦截任何资源。
- 拦截器只会对控制器中的方法进行拦截。
-
拦截器也是AOP思想的一种实现方式
-
想要自定义拦截器,需要实现HandlerInterceptor接口。
2.自定义拦截器步骤
第一步,创建类,实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
/**
* controller方法执行前,进行拦截的方法
*
* @param request
* @param response
* @param handler
* @return return true放行,return false拦截可进行跳转或重定向
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true;
}
}
第二步,配置在springMVC中配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法拦截 -->
<mvc:mapping path="/interceptor/*"/>
<!-- 哪些方法不拦截 -->
<!--=<mvc:exclude-mapping path=""/>-->
<!-- 注册拦截器对象 -->
<bean class="com.lazy.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
第三步,测试
@Controller
@RequestMapping("/interceptor")
public class InterceptorTestController {
@RequestMapping("/testPreHandle")
public String testPreHandle(){
System.out.println("PreHandle");
return "success";
}
}
<a href="interceptor/testPreHandle">testPreHandle</a>
3.HandlerInterceptor接口中的方法
1. preHandle方法是controller方法执行前拦截的方法
1. 可以使用request或者response跳转到指定的页面
2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
3. return false不放行,不会执行controller中的方法。
-
postHandle是controller方法执行后执行的方法,在JSP视图执行前。
- 可以使用request或者response跳转到指定的页面
- 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
-
postHandle方法是在JSP执行后执行
- request或者response不能再跳转页面了
4.配置多个拦截器
多个拦截器的情况与多个过滤器一致,即按照配置的顺序来进行拦截
拦截不同时:
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法拦截 -->
<mvc:mapping path="/interceptor/*"/>
<!-- 哪些方法不拦截 -->
<!--=<mvc:exclude-mapping path=""/>-->
<!-- 注册拦截器对象 -->
<bean class="com.lazy.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/another/*"/>
<bean class="com.lazy.interceptor.AnotherInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截重叠或相同时:
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法拦截 -->
<mvc:mapping path="/interceptor/*"/>
<!-- 哪些方法不拦截 -->
<!--=<mvc:exclude-mapping path=""/>-->
<!-- 注册拦截器对象 -->
<bean class="com.lazy.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lazy.interceptor.AnotherInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>