注意:其中里面的springmvc.xml和web.xml的配置文件和前面一样
success.jsp文件还是在WEB-INF的pages目录下,里面就只有执行成功语句
@Controller()
@RequestMapping("user")
public class UserController {
/**
* 返回String
* @param model
* @return
*/
@RequestMapping("testString")
public String testString(Model model) {
System.out.println("testString方法执行了...");
User user = new User();
user.setUsername("小华");
user.setPassword("123");
user.setAge(16);
model.addAttribute("user", user);
return "success";
}
}
@Controller()
@RequestMapping("user")
public class UserController {
/**
* 返回void
* @param request
* @param response
*/
@RequestMapping("testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法执行了...");
//1.编写请求转发的程序
// request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response );
//2.重定向
// response.sendRedirect(request.getContextPath()+"/index.jsp");
//设置中文乱码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//3.直接进行响应
response.getWriter().print("你好");
return;
}
}
ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
该对象中有像个经常使用的方法
1.addObject(String attributeName, Object attributeValue)
//添加模型到该对象中
//在jsp页面中可以用el表达式来获取数据,例如:${attributeName}
public ModelAndView addObject(String attributeName, Object attributeValue) {
this.getModelMap().addAttribute(attributeName, attributeValue);
return this;
}
2.setView(@Nullable View view)
//用于设置逻辑视图名称,视图解析器会根据名称前往指定的视图
@Nullable
public View getView() {
return this.view instanceof View ? (View)this.view : null;
}
@Controller()
@RequestMapping("user")
public class UserController {
@RequestMapping("testModelAndView")
public ModelAndView testModelAndView() {
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView方法执行了...");
//模拟数据库中查询出User对象
User user = new User();
user.setUsername("张三");
user.setPassword("456");
user.setAge(18);
//把user对象存储到mv对象中,也会把user对象存入到request对象
mv.addObject("user",user );
/*
原理和testString方式差不多: model.addAttribute("user", user);
return "success";
都是通过扫描视图解析器形成的
而且上述的最终底层原理也是通过ModelAndView来进行实现的
*/
//跳转到哪个页面
mv.setViewName("success");
return mv;
}
}
是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址。
是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL。
转发(forward):转发地址栏路径不变,转发只能访问当前服务器下的资源,转发是一次请求,可以使用request对象来共享数据
重定向(redirect):地址栏发生变化,重定向可以访问其他站点(服务器)的资源,重定向是两次请求。不能使用request对象来共享数据
转发(forward):转发页面和转发到的页面可以共享request里面的数据.
重定向(redirect):不能共享数据.
转发(forward):一般用于用户登陆的时候,根据角色转发到相应的模块.
重定向(redirect):一般用于用户注销登陆时返回主页面和跳转到其它的网站等
转发(forward):高
重定向(redirect):低
/**
* 使用关键字进行转发和重定向
* @return
*/
@RequestMapping("testForwardOrRedirect")
public String testForwardOrRedirect () {
System.out.println("testForwardOrRedirect方法执行了...");
//使用转发的方法
// return "forward:/WEB-INF/pages/success.jsp";
//使用重定向的方法
// (为啥不用写request.getContextPath()来获取根目录进行添加上去,因为使用关键字的方式底层已经帮忙实现了根路径的添加)
return "redirect:/index.jsp";
}
该注解用于将Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的数据如:json,xml 等,通过 Response 响应给客户端
/**
* 模拟异步请求响应
*/
@RequestMapping("testAjax")
public @ResponseBody User testAjax(@RequestBody User user) {
System.out.println("testAjax方法执行了...");
//客户端发送ajax请求,传的是json字符串,后端把json字符串封装带user对象中
System.out.println(user);
//做响应,模拟查询数据库
user.setUsername("wangwu");
user.setPassword("456");
//做响应
return user;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>响应页面</title>
<%-- 引入jquery文件 --%>
<script src="js/jquery.min.js"></script>
<script>
//页面加载,绑定单击事件
$(function () {
$("#btn").click(function () {
// alert("hello btn");
//发送ajax请求
$.ajax({
// 编写json格式,设置属性值
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"username":"nihao","password":"123","age":12}',
dataType:"json",
type:"post",
success:function (data) {
//data服务器响应的json的数据,进行解析
alert(data);
alert(data.username);
alert(data.age);
}
});
});
})
</script>
</head>
<body>
<a href="user/testString">testString</a>
<br>
<a href="user/testVoid">testVoid</a>
<br>
<a href="user/testModelAndView">testModelAndView</a>
<br>
<a href="user/testForwardOrRedirect">testForwardOrRedirect</a>
<br>
<button id="btn">发送ajax请求</button>
</body>
</html>
文件上传的必要前提:
①form 表单的 enctype 取值必须是:multipart/form-data
(默认值是:application/x-www-form-urlencoded)
enctype:是表单请求正文的类型
②method 属性取值必须是 Post
③提供一个文件选择域 < input type=”file” />
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>传统方式文件上传</h3>
<form action="user/fileUnload1" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
<h3>SpringMVC文件上传</h3>
<form action="user/fileUnload2" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
<h3>跨服务器文件上传</h3>
<form action="user/fileUnload3" method="post" enctype="multipart/form-data">
上传文件:<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
</body>
</html>
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 传统方式文件上传
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/fileUnload1")
public String fileUnload1(HttpServletRequest request) throws Exception {
System.out.println("传统方式文件上传");
// 使用fileupload组件完成文件上传
// 上传位置
String path = request.getSession().getServletContext().getRealPath("/uplaods/");
// 判断,该路径是否存在
File file = new File(path);
if(!file.exists()) {
// 创建该文件夹
file.mkdirs();
}
// 解析request对象,获取上传文件项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 解析request
List<FileItem> items = fileUpload.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));
// 删除临时文件
item.delete();
}
}
return "success";
}
说明:传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。并且上传完成之后,浏览器可能跳转
/**
* SpringMVC方式文件上传
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/fileUnload2")
public String fileUnload2(HttpServletRequest request, MultipartFile upload) throws Exception {
System.out.println("SpringMVC方式文件上传");
// 使用fileupload组件完成文件上传
// 上传位置
String path = request.getSession().getServletContext().getRealPath("/uplaods/");
// 判断,该路径是否存在
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";
}
在实际开发中,我们会有很多处理不同功能的服务器。
例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器
/**
* 跨服务器方式文件上传
* @return
* @throws Exception
*/
@RequestMapping("/fileUnload3")
public String fileUnload3(MultipartFile upload) throws Exception {
System.out.println("跨服务器方式文件上传");
//定义上传文件服务器路径
String path = "http://localhost:9090/uploads/";
//说明上传文件项
//获取上传文件的名称
String fileName = upload.getOriginalFilename();
//把文件的名称色湖之唯一值,uuid
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";
}
①过滤器是 servlet 规范中的一部分,任何 javaweb 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
②过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是
jsp,html,css,image 或者 js 是不会进行拦截的
/**
* 自定义拦截器
*/
public class MyInterceptor1 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中的preHandle方法执行了...前111");
// request.getRequestDispatcher("WEB-INF/pages/error.jsp").forward(request,response );
return true;
}
/**
* 后处理方法,controller方法执行后,success.jsp执行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor中的postHandle方法执行了...后111");
}
/**
* success.jsp执行之后,该方法会执行(不能进行页面跳转因为已经执行了success.jsp页面,一般用于释放资源的作用)
* @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("MyInterceptor中的afterCompletion方法执行了...最后111");
}
}
/**
* 控制方法
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testInterceptor")
public String testInterceptor() {
System.out.println("testInterceptor控制器方法执行了...");
return "success";
}
}
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置拦截器 -->
<mvc:interceptor>
<!-- 要拦截的方法 -->
<mvc:mapping path="/user/*"/>
<!-- 不要拦截的方法(意思:就是说上面拦截的方法和下面的不要拦截的方法实现一个就可以了)
-->
<!--<mvc:exclude-mapping path=""></mvc:exclude-mapping>-->
<!-- 配置拦截器对象 -->
<bean class="com.hugong.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
<!-- 配置另外一个拦截器 -->
<mvc:interceptor>
<!-- 要拦截的方法 -->
<mvc:mapping path="/**"/>
<!-- 不要拦截的方法(意思:就是说上面拦截的方法和下面的不要拦截的方法实现一个就可以了)
-->
<!--<mvc:exclude-mapping path=""></mvc:exclude-mapping>-->
<!-- 配置拦截器对象 -->
<bean class="com.hugong.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>