HelloControll.java:
@Controller
public class HelloControll {
@RequestMapping("hello")//使方法能够接收请求,用于绑定请求地址
public ModelAndView hello(){
System.out.println("hello springmvc...");
ModelAndView mav = new ModelAndView();
//设置模型数据,用于传递到jsp
mav.addObject("msg", "hello springmvc......");
//设置视图名字,用于响应用户
mav.setViewName("/WEB-INF/jsp/hello.jsp");
return mav;
}
}
web.xml:
<!--核心控制器的配置 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载springmvc核心配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
springmvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置controller扫描包 -->
<context:component-scan base-package="com.itheima.springmvc.controller" />
</beans>
ItemController.java:
@Controller
public class ItemController
{
@RequestMapping("itemList")
public ModelAndView itemList() {
ModelAndView mav = new ModelAndView();
//模拟查询商品列表
List<Item> list = Arrays.asList(new Item(1, "冰箱", 1999, new Date(), "冰箱很冷"),
new Item(2,"冰箱2",1999,new Date(),"冰箱很凉"),
new Item(3,"冰箱2",1999,new Date(),"冰箱很凉1"),
new Item(4,"冰箱2",1999,new Date(),"冰箱很凉2"));
mav.addObject("itemList",list);
//mav.setViewName("/WEB-INF/jsp/itemList.jsp");
mav.setViewName("itemList" );
return mav;
}
}
<form action="${pageContext.request.contextPath }/queryItem.action" method="post">
${pageContext.request.contextPath}是JSP取得绝对路径的方法,等价于<%=request.getContextPath()%> 。
也就是取出部署的应用程序名或者是当前的项目名称
比如我的项目名称是demo1在浏览器中输入为http://localhost:8080/demo1/a.jsp ${pageContext.request.contextPath}或<%=request.getContextPath()%>取出来的就是/demo1,而"/"代表的含义就是http://localhost:8080
故有时候项目中这样写${pageContext.request.contextPath}/a.jsp
HandlerMapping:处理器映射器,用于绑定url请求是由哪个方法来处理
HanderAdapoter:处理器适配器,用于实例化控制器并调用控制器中的方法
<!--配置注解驱动,相当于同时使用最新处理器映射跟处理器适配器,对json数据响应提供支持 -->
<mvc:annotation-driven></mvc:annotation-driven>
ViewResolver:视图解析器
<!--配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
SpringMVC是一个MVC的框架
springmvc与mybatis整合:
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemMapper itemMapper;
@Override
public List<Item> getItemList() {
return itemMapper.selectByExample(null);
}
@Override
public Item getItemById(Integer id) {
return itemMapper.selectByPrimaryKey(id);
}
@Override
public void updateItem(Item item) {
itemMapper.updateByPrimaryKeySelective(item);
}
}
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping("itemList")
public ModelAndView itemList() {
ModelAndView mav = new ModelAndView();
List<Item> itemList = itemService.getItemList();
mav.addObject("itemList", itemList);
// mav.setViewName("/WEB-INF/jsp/itemList.jsp");
mav.setViewName("itemList");
return mav;
}
/**
* 跟据ID查询商品信息,跳转修改商品页面
* 演示默认支持的参数传递
* Model/ModelMap返回数据模型
* @param request
* @param response
* @param session
* @return
*/
/*@RequestMapping("itemEdit")
public String itemEdit(Model model,ModelMap modelMap,HttpServletRequest request, HttpServletResponse response, HttpSession session) {
String idStr = request.getParameter("id");
System.out.println("response:" + response);
System.out.println("session:" + session);
// 查询商品信息
Item item = itemService.getItemById(new Integer(idStr));
//model返回数据模型
model.addAttribute("item", item);
//mav.addObject("item", item);
return "itemEdit";
}*/
}
//简单参数绑定,参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
@RequestMapping("itemEdit")
public String itemEdit(Model model,@RequestParam(value="id",required=true,defaultValue="1") Integer ids) {
// 查询商品信息
Item item = itemService.getItemById(ids);
//model返回数据模型
model.addAttribute("item", item);
//mav.addObject("item", item);
return "itemEdit";
}
/**
* 修改商品
* 演示pojo参数绑定
* @param item
* @return
*/
@RequestMapping("updateItem")
public String updateItem(Item item,Model model){
itemService.updateItem(item);
model.addAttribute("item", item);
model.addAttribute("msg", "修改商品信息成功");
return "itemEdit";
}
//传递pojo有一个关键点:只要表单里面的元素的name属性跟pojo的属性一一对应的上,就可以提交过来了
<!-- 解决post乱码问题 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置编码参是UTF8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
包装的pojo的属性:
通过(.)传递属性
<tr>
<td>商品名称:<input type="text" name="item.name"></td>
<td>商品价格:<input type="text" name="item.price"></td>
</tr>
@RequestMapping("queryItem")
public String queryItem(QueryVo vo,Model model){
if(vo.getItem() != null){
System.out.println(vo.getItem());
}
//模拟搜索商品
List<Item> itemList = itemService.getItemList();
model.addAttribute("itemList", itemList);
return "itemList";
}
三层架构(持久层,service层,控制层)是构建代码的思维,mvc主要偏向控制器和web块,
mvc是设计模式,三层架构是构建代码的方法
数据参数绑定:
List参数绑定:
${status.index} 输出行号,从0开始
${status.count} 输出行号,从1开始
@RequestMapping("queryItem")
public String queryItem(QueryVo vo, Integer[] ids, Model model) {
if (vo.getItem() != null) {
System.out.println(vo.getItem());
}
if (ids != null && ids.length > 0) {
for (Integer id : ids) {
System.out.println(id);
}
}
if (vo.getItems() != null && vo.getItems().size() > 0) {
for (Item item : vo.getItems()) {
System.out.println(item);
}
}
// 模拟搜索商品
List<Item> itemList = itemService.getItemList();
model.addAttribute("itemList", itemList);
return "itemList";
}
<c:forEach items="${itemList }" var="item" varStatus="status">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"></td>
<%-- <td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td> --%>
<td>
<input type="hidden" name="items[${ status.index }].id" value="${item.id}">
<input type="text" name="items[${ status.index }].name" value="${item.name }"></td>
<td><input type="text" name="items[${ status.index }].price" value="${item.price }"></td>
<td>
<%-- <fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/> --%>
<input type="text" name="items[${ status.index }].createtime" value='<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>'>
</td>
<td><input type="text" name="items[${ status.index }].detail" value="${item.detail }"></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
public class QueryVo {
private Item item;
private Integer[] ids;
private List<Item> items;
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public Integer[] getIds() {
return ids;
}
public void setIds(Integer[] ids) {
this.ids = ids;
}
自定义参数绑定:转换器:Converter
/**
* 日期转换器
* S:source 要转换的源类型
* T:目标,要转换成的数据类型
* @author Steven
*
*/
public class DateConvert implements Converter<String, Date> {
@Override
public Date convert(String source) {
Date result = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
result = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return result;
}
}
springmvc使用自定义转换器:
<!-- 配置注解驱动,相当于同时使用最新处理器映射跟处理器适配器,对json数据响应提供支持 -->
<!-- 使用自定义转换器 -->
<mvc:annotation-driven conversion-service="MyConvert" />
<!-- 定义转换器 -->
<bean id="MyConvert" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.itheima.springmvc.utils.DateConvert" />
</set>
</property>
</bean>
方法返回值:
@RequestMapping("queryVoid")
public void queryVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// request响应用户请求
// request.setAttribute("msg", "这个是request响应的消息");
// request.getRequestDispatcher("/WEB-INF/jsp/msg.jsp").forward(request,
// response);
// 假设这里是跟据id查询商品信息,搜索不到商品
if (true) {
throw new MyException("你查找的商品不存在,请确认信息!");
}
int i = 1 / 0;
// response响应用户请求
// response.sendRedirect("itemList.action");
// 设置响应的字符编码
// response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter printWriter = response.getWriter();
printWriter.println("这个是response打印的消息");
}
乱码问题:
提交问题:
post乱码:过滤器解决
get乱码:tomcat配置 URIEncoding="utf-8"
响应乱码:
response乱码:获取getWriter之前,response.setCharacterEncoding("utf-8");
Springmvc中异常处理:
做一个全局异常处理器,处理所有没有处理过的运行时异常用于更友好地提示用户。
public class CustomerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object hanlder,
Exception ex) {
String result = "系统发生异常了,请联系管理员!";
//自定义异常处理
if(ex instanceof MyException){
result = ((MyException)ex).getMsg();
}
ModelAndView mav = new ModelAndView();
mav.addObject("msg", result);
mav.setViewName("msg");
return mav;
}
}
springmvc.xml配置异常处理器:
<!-- 配置全局异常处理器 -->
<bean class="com.itheima.springmvc.exception.CustomerExceptionResolver"/>
自定义异常类,修改异常处理器,加上异常判断:
public class MyException extends Exception {
private String msg;
public MyException() {
super();
}
public MyException(String msg) {
super();
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
@RequestMapping("queryVoid")
public void queryVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// request响应用户请求
// request.setAttribute("msg", "这个是request响应的消息");
// request.getRequestDispatcher("/WEB-INF/jsp/msg.jsp").forward(request,
// response);
// 假设这里是跟据id查询商品信息,搜索不到商品
if (true) {
throw new MyException("你查找的商品不存在,请确认信息!");
}
int i = 1 / 0;
// response响应用户请求
// response.sendRedirect("itemList.action");
// 设置响应的字符编码
// response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter printWriter = response.getWriter();
printWriter.println("这个是response打印的消息");
}
图片上传:配置虚拟目录,加入上传功能需要的jar包,配置多媒体处理器
<!-- 配置多媒体处理器 -->
<!-- 注意:这里id必须填写:multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上传文件大小 -->
<property name="maxUploadSize" value="8388608" />
</bean>
@RequestMapping(value = "updateItem", method = { RequestMethod.POST, RequestMethod.GET })
public String updateItem(Item item, MultipartFile pictureFile, Model model) throws Exception {
// 图片新名字
String newName = UUID.randomUUID().toString();
// 图片原来的名字
String oldName = pictureFile.getOriginalFilename();
// 后缀
String sux = oldName.substring(oldName.lastIndexOf("."));
// 新建本地文件流
File file = new File("D:\\WebWork\\" + newName + sux);
// 写入本地磁盘
pictureFile.transferTo(file);
// 保存图片到数据库
item.setPic(newName + sux);
itemService.updateItem(item);
model.addAttribute("item", item);
model.addAttribute("msg", "修改商品信息成功");
return "itemEdit";
// return "forward:itemList.action";
// return "redirect:itemList.action";
}
post请求: <form id="itemForm" action="${pageContext.request.contextPath }/updateItem.action" enctype="multipart/form-data" method="post">
<tr>
<td>商品图片</td>
<td>
<c:if test="${item.pic !=null}">
<img src="/pic/${item.pic}" width=100 height=100/>
<br/>
</c:if>
<input type="file" name="pictureFile"/>
</td>
</tr>
json交互:
response可以响应json串
@RequestMapping("getItem")
@ResponseBody
public Item getItem(@RequestBody Item itemIn) {
System.out.println(itemIn);
// Item item = itemService.getItemById(1);
itemIn.setName("手机");
return itemIn;
}
拦截器:
/**
* 自定义拦截器
* @author Steven
*
*/
public class MyInterceptor implements HandlerInterceptor {
//方法执行后被执行
//处理异常,清资源,记录日志等等
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("MyInterceptor.afterCompletion.......");
}
//方法执行之后,返回ModelAndView之前被执行
//设置页面的共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("MyInterceptor.postHandle.......");
}
//进入方法前被执行
//登录拦截,权限验证等等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("MyInterceptor.preHandle.......");
//true放行,false拦截
return true;
}
}
拦截器案例应用,登录拦截器
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/login.action">
用户名:<input type="text" name="username" /><br>
密码:<input type="password" name="password" /><br>
<input type="submit">
</form>
</body>
</html>
1、有一个登录页面,需要写一个controller访问页面
2、登录页面有一提交表单的动作。需要在controller中处理。
a) 判断用户名密码是否正确
b) 如果正确 想session中写入用户信息
c) 返回登录成功,或者跳转到商品列表
3、拦截器。
a) 拦截用户请求,判断用户是否登录
b) 如果用户已经登录。放行
c) 如果用户未登录,跳转到登录页面。
/**
* 用户请求处理器
* @author Steven
*
*/
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping("toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("login")
public String login(String username,String password,HttpSession session){
if(username.equals("admin")){
session.setAttribute("username", username);
return "redirect:/itemList.action";
}
return "login";
}
}
/**
* 登录拦截器
* @author Steven
*
*/
public class LoginInterceptor implements HandlerInterceptor {
//方法执行后被执行
//处理异常,清资源,记录日志等等
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
//方法执行之后,返回ModelAndView之前被执行
//设置页面的共用参数等等
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
}
//进入方法前被执行
//登录拦截,权限验证等等
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
//判断用户有没有登录
Object object = request.getSession().getAttribute("username");
if(object == null){
response.sendRedirect(request.getContextPath() + "/user/toLogin.action");
}
//true放行,false拦截
return true;
}
}
<!-- 拦截器配置 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- /**拦截所有请求,包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.itheima.springmvc.interceptor.MyInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<!-- /**拦截所有请求,包括二级以上目录 -->
<mvc:mapping path="/**"/>
<bean class="com.itheima.springmvc.interceptor.MyInterceptor2" />
</mvc:interceptor>
<mvc:interceptor>
<!-- /**拦截所有请求,包括二级以上目录 -->
<mvc:mapping path="/**"/>
<!-- 配置不拦截目录 -->
<mvc:exclude-mapping path="/user/**"/>
<bean class="com.itheima.springmvc.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>