为了效果的展示,我们将隐藏的数据id显示出来。简单的数据回显,我们使用model.addAttribute方法设置key一致。
数据在修改.jsp得到展示
需求:在商品查询列表页面,用户选择要删除的商品,批量删除商品。
在controller方法中如何将批量提交的数据绑定成数组类型。
需求:批量修改商品信息提交
先进入批量修改商品页面,填写信息,点击提交。
通过查询所有将结果展示批量修改.jsp
itemsList:controller方法形参包装类型中list的属性名。
itemsList[0]或itemsList[1]。。,[]中是序号,从0开始。
itemsList[].name:name就是controller方法形参包装类型中list中pojo的属性名
需求:在商品修改页面,增加图片上传的功能。
操作流程:
用户进入商品修改页面
上传图片
点击提交(提交的是图片和商品信息)
再次进入修改页面,图片在商品修改页面展示
切记:不要把图片上传到工程 目录 ,不方便进行工程 维护。
实际电商项目中使用专门图片服务器(http,比如apache、tomcat)。
本教程使用图片虚拟目录,通过虚拟目录 访问硬盘上存储的图片目录 。
图片目录中尽量进行目录分级存储,提高访问速度(提交i/o)。
虚拟 目录 设置:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>5242880value>
property>
bean>
json数据配置的方式有两种:
第一种:Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换
在处理器适配器中注入MappingJacksonHttpMessageConverter
第二种:使用:mvc:annotation-driven 对json数据响应提供支持
<mvc:annotation-driven conversion-service="conversionService" />
请求页面
function requestJson() {
$.ajax({
url : "${pageContext.request.contextPath }/requestJson.action",
type : "post",
contentType : "application/json;charset=utf-8",
//请求json数据,使用json表示商品信息
data : '{"name":"手机","price":1999}',
success : function(data) {
alert(data.name);
}
});
}
controller方法接收并返回:
// 传入Json响应Json
@RequestMapping("/requestJson")
public @ResponseBody ItemsCustom requestJson(@RequestBody ItemsCustom itemsCustom, HttpServletRequest request) {
return itemsCustom;
}
请求页面:
function responseJson() {
$.ajax({
url : "${pageContext.request.contextPath }/responseJson.action",
type : "post",
// contentType : "application/json;charset=utf-8",
//请求json数据,使用json表示商品信息
data : "name=手机&price=3999",
success : function(data) {
alert(data.name);
}
});
}
controller方法接收并返回:
// 传入key/value响应Json
@RequestMapping("/responseJson")
public @ResponseBody ItemsCustom responseJson(ItemsCustom itemsCustom) {
return itemsCustom
}
需求:一般项目中都需要作异常处理,基于系统架构的设计考虑,使用统一的异常处理方法。
系统中异常类型有哪些?
包括预期可能发生的异常、运行时异常(RuntimeException),运行时异常不是预期会发生的。
针对预期可能发生的异常,在代码手动处理异常可以try/catch捕获,可以向上抛出。
针对运行时异常,只能通过规范代码质量、在系统测试时详细测试等排除运行时异常。
针对预期可能发生的异常,定义很多异常类型,这些异常类型通常继承于Exception。
这里定义一个系统自定义异常类:
/**
* 系统自定义的异常类型,实际开发中可能要定义多种异常类型
* @author SYJ
*/
public class CustomException extends Exception {
// 异常信息
private String message;
public CustomException() {
super();
}
public CustomException(String message) {
super();
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
要在一个统一异常处理的类中要处理系统抛出的所有异常,根据异常类型来处理。
前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程中,如果遇到异常,进行异常处理。
在系统中自定义统一的异常处理器,写系统自己的异常处理代码。
定义统一异常处理器类
根据不同的异常类型进行异常处理。
系统自定义的异常类是CustomException,在controller方法中、service方法中手动抛出此类异常。
针对系统自定义的CustomException异常,就可以直接从异常类中获取异常信息,将异常处理在错误页面展示
针对非CustomException异常,对这类重新构造成一个CustomException,异常信息为“系统发生异常了,请联系管理员”,此类错误需要在系统测试阶段去排除。
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
// 输出异常(方便调试)
ex.printStackTrace();
// 定义异常信息在指定页面显示
String message = null;
CustomException customException = null;
// 统一处理异常代码
// 针对系统自定义的CustomException异常,就可以直接从异常类中获取异常信息,将异常信息在页面展示
// 异常信息
if (ex instanceof CustomException) {
customException = (CustomException) ex;
} else {
// 针对非CustomException异常,我们对这类的信息重新尽心异常类型的构造,异常信息为“系统发生异常了,请联系管理员”
customException = new CustomException("系统发生异常了,请联系管理员");
}
message = customException.getMessage();
request.setAttribute("message", message);
try {
request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
} catch (ServletException | IOException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
将定义好的统一异常处理类在springmvc.xml中进行配置(因为实现了HandlerExceptionResolver接口所以不需要加bean的id)
非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&…
RESTful的url是简洁的:http:// localhost:8080/items/editItems/1
参数通过url传递,rest接口返回json数据
需求:根据id查看商品信息,商品信息查看的连接使用RESTful方式实现,商品信息以json返回。
第一步更改DispatcherServlet配置
<servlet>
<servlet-name>springmvc_restservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring/springmvc.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvc_restservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
第二步参数通过url传递
配置页面:
在controller中进行接收:
// RESTful测试
@RequestMapping("/viewItems/{id}")
// 根据商品id查看商品信息rest接口
// @RequestMapping中指定restful方式的ur1中的参教,参教需要用 { } 包起来
// @PathVariable将ur1中的 { } 包起参数和形参进行绑定
public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception {
// 调用 service查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(id);
return itemsCustom;
}
设置静态资源解析
当DispatcherServlet拦截/开头的所有请求,对静态资源的访问就报错:
需要通过设置对静态资源进行解析.
访问/js/**的url从工程下/js/下解析。
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/img/" mapping="/img/**" />
用户请求到DispatherServlet中,DispatherServlet调用HandlerMapping查找Handler,HandlerMapping返回一个拦截的链儿(多个拦截),springmvc中的拦截器是通过HandlerMapping发起的。
需要实现HandlerInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor {
// 执行Handler之后执行
// 作为系统的统一异常处理,进行方法的执行性能的监控,在preHandler中设置一个时间点,在afterCompletion设置一个时间点,两个时间的差值
// 实现系统统一对日志的处理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("MyInterceptor1...afterCompletion...");
}
// 在执行handler返回ModelAndView之前执行
// 如果需要向页面提供数据或者配配置视图信息,可以使用此方法从ModelAndView执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1...postHandle...");
}
// 在handler之前执行
// 主要用于用户认证的校验、用户的权限校验
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("MyInterceptor1...preHandle...");
// 如果为true表示放行,如果返回false表示拦截之后不继续执行handler
return true;
}
}
配置全局的拦截器,DispatcherServlet将配置的全局拦截器加载到所有的HandlerMapping。
在springmvc.xml中配置:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.syj.ssm.interceptor.MyInterceptor1">bean>
mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.syj.ssm.interceptor.MyInterceptor2">bean>
mvc:interceptor>
mvc:interceptors>
需求:用户访问系统的资源(url),如果用户没有进行身份认证,进行拦截,系统跳转登陆页面,如果用户已经认证通过,用户可以继续访问系统
的资源。
登录页面的开发:
<title>用户的登录</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login.action" method="post">
用户名:<input type="text" name="usercode" /><br>
密 码:<input type="password" name="password" /><br>
<input type="submit" value="登录" >
</form>
</body>
</html>
登录和退出的controller的开发:
@Controller
public class Login {
@RequestMapping("/login")
// 用户的登录提交的方法
public String login(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
// 调用service通过查询数据库,验证账号和密码的正确性
// 执行各种操作
// 获取用户名
String usercode = (String) request.getParameter("usercode");
// 将用户名存储到session中
session.setAttribute("usercode", usercode);
// 验证成功之后转跳到查询的列表
return "redirect:/item/queryItems.action";
}
// 用户的退出
@RequestMapping("/logout")
public String logout(HttpSession session) {
// session失效
session.invalidate();
return "redirect:/login.jsp";
}
}
登录拦截器的开发:
public class LoginInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("LoginInterceptor ... afterCompletion ...");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("LoginInterceptor ... postHandle ...");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("LoginInterceptor ... preHandle ...");
// 1、如果url是公开地址(比如网站的首页人人都可以查看)
// 得到请求的地址
StringBuffer url = request.getRequestURL();
if (url.indexOf("login.action") >= 0) {
return true;
}
// 2、判断session中是否存在该用户
HttpSession session = request.getSession();
String usercode = (String) session.getAttribute("usercode");
// 如果存在就放行
if (usercode != null && usercode.length() > 0 && !"".equals(usercode.trim())) {
return true;
}
// 执行到这里说明该用户没有登录或者不存在
request.getRequestDispatcher("/login.jsp").forward(request, response);
return false;
}
}
springmvc是通过方法的形参接收参数,在使用时可以以单例方式使用,建议使用单例。
struts是通过成员变量接收参数,在使用时必须以多例方式使用。
springmvc是基于方法开发,struts基于类开发。
springmvc将一个请求的Method和Handler进行关联绑定,一个method对应一个Handler。
springmvc开发以方法为单位进行开发,方法更帖进service(业务方法)。
经过实际测试,发现struts标签解析速度比较慢,建议在实际开发时使用jstl。