第一章 响应数据和结果视图
1.1 响应的几种方法
1.1.1 返回String
@RequestMapping("/testString")
public String testString(Model model){
System.out.println("testString执行了");
User user1 = new User();
user1.setUsername("zhangsan");
user1.setPassword("123");
model.addAttribute("user1",user1);
return "success";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>执行成功</h3>
${ user1.username }
${ user1.password }
</body>
</html>
1.1.2 返回void
以往是根据方法的String类型的返回值配合视图解析器来确定跳转到哪个页面的,但如果返回值是void呢
/**
* 不会再请求视图解析器
* 请求转发是一次请求,所以路径不用写项目名称,从WEB-INF开始即可
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
System.out.println("testVoid执行了");
//方法一——请求转发
//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//方法二——重定向
//WEB-INF里的文件受保护所以不能通过重定向访问
//response.sendRedirect(request.getContextPath()+"/index.jsp");
//方法三——直接输出
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().print("测试输出流输出");
return ;
}
1.1.3 返回ModelAndView对象
SpringMVC的内置对象
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
System.out.println("testString执行了");
ModelAndView mv = new ModelAndView();
User user1 = new User();
user1.setUsername("lisi");
user1.setPassword("123");
mv.addObject("user1",user1);
//跳转到哪个页面
mv.setViewName("success");
return mv;
}
//1.1.1的底层原理也是使用的这个
1.2 转发和重定向
关键字方式进行转发或重定向
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect(){
System.out.println("testForwardOrRedirect执行了");
//请求转发
//return "forward:/WEB-INF/pages/success.jsp";
//重定向
//底层默认加了项目路径,所以这里不用加
return "redirect:/index.jsp";
}
1.3 ResponseBody响应json数据
客户端发送带着json数据的请求,服务器拿到json数据做一些处理(比如从数据库查询)后返回一个json数据的响应
步骤
① webapp下创建js/jquery.min.js(导入jquery库以便使用)
② response.jsp
<head>
<%--引入js文件--%>
<script src="js/jquery.min.js"></script>
<script>
$(function(){
$("#btn").click(function(){
//发送ajax请求
$.ajax({
//编写json格式,设置属性和值
url:"user/testAjax", //请求会交给这个url处理
contentType:"application/json;charset=UTF-8",
data:'{"username":"haha","password":"123","age":30}', //请求体
dataType:"json",
type:"post",
//data指服务器端响应的json数据,可以进行解析
success:function(data){
alert(data);
alert(data.username);
alert(data.password);
}
});
});
});
</script>
</head>
<body>
<button id="btn">发送ajax的请求</button>
</body>
tips:请求静态文件会被前端控制器拦截,要在springmvc.xml中设置不拦截
<!--告诉前端控制器 哪些资源不用拦截-->
<mvc:resources location="/js/" mapping="/js/**"/>
③ 编写接收并处理请求的方法
/**
* 模拟异步请求和响应
*/
@RequestMapping("/testAjax")
//@RequestBody: 将请求体的内容(json字符串)封装到参数User user中 因为其属性名称都是一一对应的
//@ResponseBody:将改变后的user作为响应体发给response.jsp,response.jsp里的data就接收到数据进行处理(处理见步骤③)
//user转成了json串返回
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("testAjax执行了");
//客户端发送ajax请求,传的是json字符串,后端把json字符串封装到了user对象中
System.out.println(user);
//做响应 模拟查询数据库
user.setUsername("lala");
user.setPassword("789");
return user;
}
第二章 SpringMVC实现文件上传
2.1 文件上传
2.1.1 前提
form 表单的enctype值是:multipart/form-data (意为多部分上传)
method为post
提供一个文件选择域
特定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>
2.1.2 传统文件上传方式
① jsp配置
<form action="user/fileupload1" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/><br />
<input type="submit" value="上传"/>
</form>
② UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/fileupload1")
public String fileupload1(HttpServletRequest request)throws Exception{
System.out.println("文件上传");
//使用fileupload组件完成文件上传
//规定上传位置
//文件路径:springmvc\springmvc_day2_fileupload\target\springmvc_day01_01_start\uploads
String path = request.getSession().getServletContext().getRealPath("/uploads/");
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//开始解析
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();
//把文件的名称设置成唯一值 这样以后上传相同文件就不会覆盖掉
String uuid=UUID.randomUUID().toString().replace("-","");
filename=uuid+"_"+filename;
//上传文件到指定路径
item.write(new File(path,filename));
//删除临时文件
item.delete();
}
}
return "success";
}
}
2.1.3 SpringMVC中文件上传方式
与传统方式的差别:框架帮助解析了request请求,不用再自己编写解析代码
① springmvc.xml配置文件解析器
<!--配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxInMemorySize" value="10485760" />
</bean>
② jsp配置
<form action="user/fileupload2" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/><br />
<input type="submit" value="上传"/>
</form>
③ UserController
@RequestMapping("/fileupload2")
//MultipartFile upload 注意这里的参数名必须跟jsp中的name一样
public String fileupload2(HttpServletRequest request, MultipartFile upload)throws Exception{
System.out.println("SpringMVC文件上传");
//使用fileupload组件完成文件上传
//规定上传位置
String path = request.getSession().getServletContext().getRealPath("/uploads/");
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//获取上传文件名称
String filename = upload.getOriginalFilename();
//把文件的名称设置成唯一值 这样以后上传相同文件就不会覆盖掉
String uuid=UUID.randomUUID().toString().replace("-","");
filename=uuid+"_"+filename;
//上传文件到指定路径
upload.transferTo(new File(path,filename));
return "success";
}
2.1.4 跨服务器上传
① 准备一个文件服务器,里面只需要在target中加入图片文件夹就可以了
② 应用服务器的jsp
<form action="user/fileupload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/><br />
<input type="submit" value="上传"/>
</form>
③ 应用服务器的controller
首先引入辅助连接的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>
//错误记录 上传时报405:要在tomcat/conf/web.xml里配置readonly false
//报409 忘记在图片服务器的target里面创建uploads了
@RequestMapping("/fileupload3")
//MultipartFile upload 注意这里的参数名必须跟jsp中的name一样
public String fileupload3(MultipartFile upload)throws Exception{
System.out.println("SpringMVC文件上传");
//使用fileupload组件完成文件上传
//规定上传位置
String path="http://localhost:9090/uploads/";//第①步的文件夹名称必须是uploads
//获取上传文件名称
String filename = upload.getOriginalFilename();
//把文件的名称设置成唯一值 这样以后上传相同文件就不会覆盖掉
String uuid=UUID.randomUUID().toString().replace("-","");
filename=uuid+"_"+filename;
//创建客户端
Client client = Client.create();
//连接文件服务器 传入文件路径
WebResource webResource = client.resource(path+filename);
//上传文件
webResource.put(upload.getBytes());
return "success";
}
第三章 SpringMVC的异常处理
按照最原始的逻辑,出现异常后会一步步向上抛出异常:dao—>service—>web—>前端控制器—>浏览器。但是把原始异常直接抛给用户是非常不友好的,所以需要在前端控制器中配置一个异常处理器组件,编写异常处理器,用来对抛过来的异常进行处理,抛给浏览器处理后的异常。
① 编写自定义异常类
**
* 自定义异常类
*/
public class SysException extends Exception{
public SysException(String message){
this.message=message;
}
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
② 在UserController中捕获并编写要抛出的自定义异常语句
@Controller
@RequestMapping("/user")
public class UserController {
//演示不处理异常的结果
@RequestMapping("/testException")
public String testException()throws SysException{
System.out.println("testException执行了");
try {
int a=10/0;
} catch (Exception e) {
e.printStackTrace();
//捕获后抛出自定义的异常
throw new SysException("这是要传送到浏览器端的自定义异常信息");
}
return "success";
}
}
③ 编写异常处理的业务逻辑(拿到异常和页面跳转)
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常的业务逻辑
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
SysException exception =null;
//拿到异常对象,判断
if(e instanceof SysException){
exception=(SysException) e;
}else{
exception=new SysException("系统维护中...");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errormsg",exception.getMessage());
//设置需要跳转到的页面
mv.setViewName("error");
return mv;
}
}
④ 编写要跳转到的页面
<html>
<head>
<title>Title</title>
</head>
<body>
${errormsg}
</body>
</html>
⑤ 配置异常处理器
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="com.stay.exception.SysExceptionResolver"></bean>
第四章 SpringMVC拦截器
类似于学servlet时的过滤器,作用是做预处理或者后处理。与Servlet中过滤器不同的是拦截器是SpringMVC独有的而且只能拦截对控制器的访问。
4.1 自定义拦截器
① 自定义拦截器类
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 拦截器预处理
* return true 表示做完处理后放行给下一个拦截器或者controller
* return false 表示不放行
* 因为参数有request和response 所以可以在拦截器中跳转至某个页面
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("第一个拦截器执行预处理工作");
//拦截器中进行页面跳转 比如跳转到错误页面 这时候如果不想再执行controller的话就要return false
//request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 后处理方法 在controller方法和success.jsp中间执行
* @param request
* @param response
* @param handler
* @param modelAndView
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {
System.out.println("第一个拦截器执行后处理工作");
//后处理中也可以执行页面跳转
//request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* 最后执行的方法 也就是在success.jsp后执行的方法
* @param request
* @param response
* @param handler
* @param ex
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("第一个拦截器的最后方法执行");
}
}
② 配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--要拦截的具体方法路径-->
<mvc:mapping path="/user/*"/>
<bean class="com.stay.interceptor.MyInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<!--要拦截的具体方法路径-->
<mvc:mapping path="/user/*"/>
<bean class="com.stay.interceptor.MyInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
然后就可以执行了,放个执行结果: