1.上传图片
- 配置虚拟目录
在tomcat上配置图片虚拟目录,双击tomcat
选中如下
点击左下角Modules
增加路径(Add Externa Web Module)
在浏览器中输入指定路径即可查看图片http://localhost:8080/724739205.jpeg
- 增加jar包
- 配置上传解析器
在springmvc.xml中配置文件上传解析器
<!-- 文件上传解析器,id必须设置为multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传大小 -->
<property name="maxUploadSize" value="5000000"></property>
</bean>
- editItem.jsp页面修改
设置表单可以进行文件上传
<!-- 上传图片是需要指定属性 enctype="multipart/form-data" -->
<!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
<form id="itemForm" action="${pageContext.request.contextPath}/updateitem.action" method="post" enctype="multipart/form-data" >
添加上传文件表格
<tr>
<td>商品图片</td>
<td>
<c:if test="${item.pic !=null}">
<img src="/${item.pic}" width=100 height=100/>
<br/>
</c:if>
<input type="file" name="pictureFile"/>
</td>
</tr>
- 在更新商品方法中添加图片上传逻辑
//更新商品
@RequestMapping("/updateItem")
public String updateItem(Item item,MultipartFile pictureFile) throws IllegalStateException, IOException{
//图片上传
//设置图片名称,不能重复,可以使用uuid
String picName=UUID.randomUUID().toString();
//获取文件名
String oriName=pictureFile.getOriginalFilename();
//获取图片后缀
String extName=oriName.substring(oriName.lastIndexOf("."));
//开始上传
pictureFile.transferTo(new File("/Users/chenjiafeng/Pictures/"+picName+extName));
//设置图片名到商品中
item.setPic(picName+extName);
//更新商品
this.itemService.updateItem(item);
return "forward:/itemEdit.action";
}
效果
2.json数据交互
- @RequestBody
作用:@RequestBody注解用于读取httpp请求到内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为Java对象并绑定到Controller方法的参数上
传统的请求参数:
itemEdit.action?id=1$name=zhangsan&age=12
现在的请求参数:使用post请求,在请求体里加入json数据
{
"id":1
"name":"测试商品"
"price":99.9
"detail":"测试商品描述"
"pic":"123456.jpg"
}
本例子应用:
@RequestBody注解实现接收http请求的json数据,将json数据 转换为Java对象进行绑定
- @ResponsBody
作用:@ResponsBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Respons响应给客户端
本例子应用:@ResponsBody注解实现将Controller方法返回Java对象转换为json响应给客户端
- 请求json,响应json实现
加入jar包
ItemController编写
// 测试json交互
@RequestMapping("testJson")
public @ResponseBody Item testJson(@RequestBody Item item) {
System.out.println(item);
return item;
}
增加js
在editItem.jsp中添加测试方法
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
$(function(){
alert(1);
var params = '{"id": 1,"name": "测试商品","price": 99.9,"detail": "测试商品描述","pic": "QQ20190315-1.jpg"}';
// $.post(url,params,function(data){
//回调
// },"json");//
$.ajax({
url : "${pageContext.request.contextPath }/testJson.action",
data : params,
contentType : "application/json;charset=UTF-8",//发送数据的格式
type : "post",
dataType : "json",//回调
success : function(data){
alert(data.name);
}
});
//alert(2);
});
配置json转换器
如果不使用注解驱动<mvc:annotation-driven/>,就需要给处理器适配器配置json转换器,参考之前的学习自定义参数绑定
在spiringmvc.xml配置文件中,给处理器适配器加入json转换器
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>
3.RESTFUL支持
Restful是一个资源定位及资源操作的风格。不是标准也不是协议,只是一个风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用Post、Delete、Put、Get,使用不同方法对资源进行操作。分别对应 添加、删除、修改、查询。
传统方式操作资源
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTFUL操作资源
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
需求
RESTFUL方式实现商品信息查询,返回json数据
- 从URL上获取参数
使用RESTful风格开发的接口,根据id查询商品,接口地址是:
http://127.0.0.1/item/1
我们需要从url上获取商品id,步骤如下:
- 使用注解@RequestMapping(“item/{id}”)声明请求的url {xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
- 使用(@PathVariable() Integer id)获取url上的数据
//使用Restful风格开发接口,实现根据id查询商品
@RequestMapping("item/{id}")
public @ResponseBody Item queryItemById(@PathVariable() Integer id) {
Item item=this.itemService.queryById(id);
return item;
}
如果@RequestMapping中表示为”item/{id}”,id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如”item/{ItemId}”则需要指定名称@PathVariable(“itemId”)。
注意两个区别
- @PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)
- 如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面
4.拦截器
定义:Spring Web MVC的处理器拦截器类似于Servlet开发中的过滤Filter,用于对处理器进行预处理和后处理。
- 拦截器定义
实现HandlerInterceptor接口,如下
public class Interceptor1 implements HandlerInterceptor {
//controller执行后且视图返回后调用此方法
//这里可得到执行controller时的异常信息
//这里可记录操作日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1-afterCompletion");
}
//controller执行后但未返回视图前调用此方法
//这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1-postHandle");
}
//Controller执行前调用此方法
//返回true表示继续执行,返回false中止执行
//这里可以加入登录校验、权限拦截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1-preHandle");
//返回true在能让controller方法执行,测试使用
return true;
}
}
public class Interceptor2 implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2-afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2-postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2-preHandle");
//返回true在能让controller方法执行
return true;
}
}
- 拦截器配置
在springmvc.xml中配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 所有的请求都进入拦截器 -->
<mvc:mapping path="/**"/>
<bean class="com.feng.ssm.terceptor.Interceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.feng.ssm.terceptor.Interceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
效果(注意拦截器方法的执行顺序)
preHandle- Controller执行前调用此方法- 按拦截器定义顺序执行
postHandle、afterCompletion-按拦截器定义逆序执行
afterCompletion只有preHandle返回true才调用
如果把拦截器Intercept1的preHandle返回flase(一旦中断,后面的拦截器不再执行)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("Interceptor1-preHandle");
return false;
}
拦截器应用
处理流程
- 有一个登录页面,需要写一个controller访问页面
- 登录页面有一提交表单的动作。需要在controller中处理。
- 判断用户名密码是否正确
- 如果正确 想session中写入用户信息
- 返回登录成功,或者跳转到商品列表
- 拦截器。
- 拦截用户请求,判断用户是否登录
- 如果用户已经登录。放行
- 如果用户未登录,跳转到登录页面
编写登录login.jsp
<body>
<form action="${pageContext.request.contextPath }/user/login.action">
<label>用户名:</label>
<br>
<input type="text" name="username">
<br>
<label>密码:</label>
<br>
<input type="password" name="password">
<br>
<input type="submit">
</form>
</body>
用户登录Controller(UserController.java)
@Controller
@RequestMapping("user")
public class UserController {
//跳转到登录页面
@RequestMapping("tologin")
public String tologin() {
return "login";
}
//用户登录
@RequestMapping("login")
public String login(String username,String password,HttpSession session) {
//校验用户登录
System.out.println(username);
System.out.println(password);
//把用户名放到session中
session.setAttribute("username", username);
return "redirect:/item/itemList.action";
}
}
编写拦截器(LoginIntercepor.java)
//Controller执行前调用此方法
//返回true表示继续执行,返回false中止执行
//这里可以加入登录校验、权限拦截等
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
//从reques中获取session
HttpSession session=request.getSession();
//从session中获取username
Object username=session.getAttribute("username");
//判断username是否为null
if(username!=null) {
//如果不为空则放行
return true;
}else {
//如果为空则跳转到登录页面
response.sendRedirect(request.getContextPath()+"/user/tologin.action");
}
return false;
}
配置拦截器
只能拦截商品到url,所有需要修改ItemController,让所有的请求都必须以item开头,如下图
@Controller
@RequestMapping("item")
public class ItemController {
}
在springmvc.xml配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/item/**" />
<bean class="com.feng.ssm.controller.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
测试:
输入http://localhost:8080/SpringMVC-mybatis2/user/tologin.action后,因为没有登录,所以自动跳转到登录页面
输入用户名密码后跳转
控制台显示