2017.2.25-2017.2.28
ssm框架整合步骤
整合dao层
mybatis和Spring整合,通过Spring管理mapper接口
使用mapper的扫描器自动扫描mapper接口在Spring中进行注册整合service层
通过Spring管理service接口
使用配置方式将service接口配置在Spring配置文件中
实现事务控制整合springmvc
由于springmvc是Spring的模块,不需要整合
第一个程序
以下借助用户查询业务来进行springmvc-Spring-mybatis框架整合
1.整合dao
创建工程引入相应jar包,创建db.properties、log4j.properties
用逆向工程创建User实体类、mapper.xml、mapper.java。为了方便扩展创建UserCustom类继承User,再创建UserQueryVo类设置User对象和UserCustom属性
在sqlMapConfig.xml中配置匿名(可选)
在Spring的dao层(applicationContext-dao.xml)配置文件中加载配置文件、配置数据源、创建sqlSessionFactory、定义mapper扫描器
<!-- 加载配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置c3p0数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注入属性值 --> <property name="driverClass" value="${jdbc.drivername}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" > <!-- 加载mybatis配置文件 --> <property name="configLocation" value="mybatis/sqlMapConfig.xml"></property> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"></property> </bean> <!-- mapper扫描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.zcw.ssm.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean>
2.整合service层
创建service接口UserService和实现类UserServiceImpl,UserService的方法和UserMapperCustom类中的方法一样。在UserServiceImpl中设置UserMapperCustom对象属性并注入,实现父类的方法调用UserMapperCustom的方法实现功能
public class UserServiceImpl implements UserService{ @Autowired private UserMapperCustom userMapperCustom; @Override public UserCustom findUserById(UserQueryVo userQueryVo) { return userMapperCustom.findUserById(userQueryVo); } }
配置service层的Spring配置文件applicationContext-service.xml,创建service接口实现类。
<!-- 用户管理 的service--> <bean id="userService" class="cn.zcw.ssm.service.impl.UserServiceImpl"></bean>
配置事务管理,创建applicationContext-transaction.xml配置文件。
<!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 引用在applicationContext-dao.xml配置的数据源 --> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置通知/增强 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 传播行为 --> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="find*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!-- aop --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.zcw.ssm.service.impl.*.*(..))"/> </aop:config>
3.整合springmvc
创建springmvc配置文件
<!-- 可以扫描controller、service。。。。 --> <context:component-scan base-package="cn.zcw.ssm.controller"></context:component-scan> <mvc:annotation-driven></mvc:annotation-driven> <!-- 视图解析器 jsp解析,默认使用jstl标签,所以classpath下得有jstl的包 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置jsp路径前缀 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 配置JSP路径后缀 --> <property name="suffix" value=".jsp"></property> </bean>
在web.xml中配置springmvc的前端控制器
<!-- 配置springmvc前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置springmvc加载的配置文件(处理器映射器、适配器等) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet。xml(这里是springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 第一种:*.action,访问以.action结尾的请求,由DispatcherServlet进行解析 第二种:/,所有的访问地址都有DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析,使用这种方式可以实现REDTful风格的url 第三种:/*,这种配置不对,这种配置最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到Handler,会报错 --> <url-pattern>*.action</url-pattern> </servlet-mapping>
编写controller,就是Handler
public class UserController implements Controller{ @Autowired private UserService userService; public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { UserQueryVo uq=new UserQueryVo(); uq.getUser().setId(1); UserCustom userCustom=userService.findUserById(uq); ModelAndView modelAndView=new ModelAndView(); //相当于setAttribute modelAndView.addObject("users",userCustom); //指定视图 modelAndView.setViewName("users/user/userList"); return modelAndView; }
}
编写JSP页面
<body> 商品列表 <table width="100%" border="1"> <c:forEach items="${users}" var="user"> <tr> <td>${user.username}</td> </tr> </c:forEach> </table> </body>
加载Spring容器
contextConfigLocation
classpath:spring/applicationContext-*.xml
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
到此ssm框架整合结束
修改功能
根据id查询用户,根据id修改用户
- dao层,利用逆向工程的mapper即可实现
service层,创建UserMapper对象属性
//根据id查询用户 @Override public UserCustom findUserById(Integer id) { User user=userMapper.selectByPrimaryKey(id); UserCustom userCustom=new UserCustom(); //将user的属性拷贝到userCustom中 BeanUtils.copyProperties(user, userCustom); return userCustom; } //根据id更新用户 @Override public void updateUser(Integer id, UserCustom userCustom) { userCustom.setId(id); userMapper.updateByPrimaryKeySelective(userCustom); }
- controller创建
@requestMapping的应用
对URL进行分类管理,可以在controller类中定义根路径,最终的访问路径为根路径+自路径
@RequestMapping("/user") public class UserController{
对http请求的方法进行限定
@RequestMapping(value="/userDetail",method={RequestMethod.POST,RequestMethod.GET})
controller方法返回值类型
- ModelAndView
- String
- 表示返回逻辑视图名,如返回:“userList”,表示返回到…userList.action中。可在此方法中创建形参Model,将数据放到Model对象中,页面访问
- 重定向,返回“redirection:userList.action”。地址栏变化,request不共享
- 转发,返回“forword:userList.action”。在此方法中设置HttpServletRequest形参,用来接收请求参数。地址栏不变,request共享
void,可设置形参request和response
- 使用request转发页面。
request.getRequestDispatcher("页面路径").forward(request,response);
- response重定向页面。
response.sendRedirect("url");
response指定响应结果。
response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");
- 使用request转发页面。
springmvc的参数绑定
将页面请求的key、value通过处理器适配器绑定到controller的形参中
参数绑定默认支持的类型:
- HttpServletRequest
- HttpServletResponse
- HttpSession
Model/ModeMap
model是一个接口,modelMap是model的实现类。最终model将数据放到request域中
@RequestParam简单类型的参数绑定
如果不是用@RequestParam,要求request传入参数名称和controller方法的性参名称一致,方可绑定成功。使用的话任意更改形参名称
public ModelAndView userDetail(@RequestParam(value="id",required=true,defaultValue="1") Integer id){
value:请求的参数值
required:value指定的值不能为空
defaultValue:指定形参默认值
自定义参数绑定实现日期类型
定义自定义参数绑定的bean
<!-- 自定义参数绑定 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 转换器 --> <property name="converters"> <list> <!-- 日期类型转换 --> <bean class="cn.zcw.ssm.controller.converter.UserDateConverter"></bean> </list> </property> </bean>
在mvc:annotation-driven中声明conversion-service属性
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
定义转换类,实现Converter接口
public class UserDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); // 转成直接返回 try { return simpleDateFormat.parse(source); } catch (java.text.ParseException e) { e.printStackTrace(); } return null; } }
springmvc和struts2的区别
springmvc基于方法开发,struts2基于类开发
springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括一个method方法。方法之行结束,形参数据销毁。
springmvc的controller开发类似于service开发
- springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类似的成员变量接受参数,无法使用单例,只能使用多例。
经过实际测试,struts2速度慢,在于实用struts标签,如果使用struts2建议使用jstl。
springmvc参数绑定–包装pojo
例如包装的pojo为UserQueryVo,页面的input标签的name要绑定到UserQueryVo的userCustom属性的username属性中,则input的name定义为userCustom.username,即<input type="text" name="userCustom.username">
springmvc参数绑定–数组绑定
例如:实现查看复选框选中的情况。
页面中复选框的name为c_name,value为String型的,则controller方法的形参定义为“String []c_name”,即页面的name与形参的name相同。
springmvc参数绑定–List
例如:批量修改用户信息。用户信息显示(input标签)在页面,手动修改并提交。
一般在封装的pojo类(如:UserQueryVo)中设置Link
服务端校验
- 控制层controller:校验页面请求的参数的合法性。在服务端控制层controller校验,不区分客户端类型(浏览器、手机客户端、远程调用)
- 业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数
- 持久层dao:一般不校验
springmvc校验
- 引入jar包,一定得注意版本(我花了大约5/6个小时来调试这个错误。原因就是我将jar包的版本给弄高了和视频讲解的不一样,然后自己右将代码给写错了。看来,脚踏实地才是捷径呀!)。
- hibernate-validator-4.3.0.jar
- jboss-logging-3.3.0.jar
- validation-api-1.0.0.GA.jar
在springmvc中配置校验器,在根路径下创建UserValidationMessages.properties校验资源文件并添加错误提示的key-value
<!-- 校验错误信息的配置文件 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <!-- 资源文件名 --> <property name="basenames"> <list> <value>classpath:UserValidationMessages</value> </list> </property> <!-- 资源文件编码格式 --> <property name="fileEncodings" value="utf-8"></property> <!-- 对资源文件内容缓存时间,单位秒 --> <property name="cacheSeconds" value="120"></property> </bean> <!-- 校验器 --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <!-- hibernate校验器 --> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property> <!-- 指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessage.properties --> <property name="validationMessageSource" ref="messageSource"></property> </bean>
将校验器注入到处理器适配器中
<mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>
在实体类的属性上添加校验注解
//user.username.length.error在校验资源文件中定义(key-value形式定义),message可以直接写成字符串 @Size(min=1,max=3,message="{user.username.length.error}") private String username;
在controller的方法形参之前添加注解(@Valid)之后添加错误结果(BindingResult),然后输出错误结果
public String userUpdate(@Valid UserCustom userCustom,BindingResult bindingResult,Integer id){ if(bindingResult.hasErrors()){ List<ObjectError> errors=bindingResult.getAllErrors(); for(ObjectError error:errors){ System.out.println(error.getDefaultMessage()); } }
测试,访问指定的handle
分组校验
创建一个接口作为分组的类
public interface ValidateGroup1 { //此接口中不必写任何方法,只用于分别校验属性 }
在pojo的校验注解中写上Groups属性,属性值为接口的class
//groups可以定义多个组 @Size(min=1,max=3,message="{user.username.length.error}",groups={ValidateGroup1.class}) private String username;
controller的方法@Validated中添加所属的组别
public String userUpdate(@Validated(value=ValidateGroup1.class) UserCustom userCustom,BindingResult bindingResult,Integer id)
数据回显
当操作出错的时候,重新回到上个页面
pojo回显
pojo数据传入controller方法之后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)
@ModelAttribute可以指定pojo回显到页面在request的key
public String userUpdate(@ModelAttribute("userCutom")){}
@ModelAttribute还可以将方法的返回值放到request中
@ModelAttribute("return") public String test(){ return "aaa"; }
- 用model
异常处理
系统中异常包括两类:预期异常和运行时异常(RuntimeException),前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试手段来减少运行时异常的发生
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理
springmvc提供了一个全局异常处理器进行统一异常处理
创建一个pojo类继承Exception
public class CustomException extends Exception{ private String message; public CustomException(String message){ super(message); this.message=message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
创建全局异常处理类,这个类实现了HandlerExceptionResolver接口,再实现其方法其实就是一个Handler
public class CustomExceptionResolver implements HandlerExceptionResolver{ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { CustomException customException=null; if(ex instanceof CustomException){ customException=(CustomException) ex; } else{ customException=new CustomException("未知异常!!!"); } ModelAndView modelAndView=new ModelAndView(); String message=customException.getMessage(); modelAndView.addObject("message", message); modelAndView.setViewName("error"); return modelAndView; } }
在springmvc中注册bean
<!-- 只要实现HandlerExceptionResolver接口就是全局异常处理器 --> <bean class="cn.zcw.ssm.exception.CustomExceptionResolver"></bean>
上传图片
在页面form中提交enctype=”multipart/form-data”的数据时,需要springmvc对multipart类型的数据进行解析
- 导入jar包
- commons-fileupload.jar
- commons-io.jar
在springmvc的配置文件中配置解析器
<!-- 配置解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置文件的最大上传尺寸 --> <property name="maxUploadSize" value="5242880"></property> </bean>
- 将表单的enctype设成“multipart/form-data”类型
- 在controller方法的形参名称设置为与文件表单的name相同
Springmvc实现json交互
RequestBody将json串转成java对象,ResponseBody将Java对象转换成json串
- 导入jar包
- jackson-core.jar
- jackson-mapper-asl.jar
配置json转换器
- 如果使用则不需配置
如果使用了单独的处理器映射器,则需要在适配器中加入
<bean class="适配器"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> </list> </property> </bean>