2017.2.25-2017.2.28
整合dao层
mybatis和SPRing整合,通过Spring管理mapper接口 使用mapper的扫描器自动扫描mapper接口在Spring中进行注册
整合service层
通过Spring管理service接口 使用配置方式将service接口配置在Spring配置文件中 实现事务控制
整合springmvc
由于springmvc是Spring的模块,不需要整合
以下借助用户查询业务来进行springmvc-Spring-mybatis框架整合
创建工程引入相应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>创建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>创建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{@Autowiredprivate 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查询用户@Overridepublic UserCustom findUserById(Integer id) { User user=userMapper.selectByPrimaryKey(id); UserCustom userCustom=new UserCustom(); //将user的属性拷贝到userCustom中 BeanUtils.copyProperties(user, userCustom); return userCustom;}//根据id更新用户@Overridepublic void updateUser(Integer id, UserCustom userCustom) { userCustom.setId(id); userMapper.updateByPrimaryKeySelective(userCustom);}controller创建对URL进行分类管理,可以在controller类中定义根路径,最终的访问路径为根路径+自路径
@RequestMapping("/user")public class UserController{对http请求的方法进行限定
@RequestMapping(value="/userDetail",method={RequestMethod.POST,RequestMethod.GET})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串");将页面请求的key、value通过处理器适配器绑定到controller的形参中
参数绑定默认支持的类型:
HttpServletRequestHttpServletResponseHttpSessionModel/ModeMap
model是一个接口,modelMap是model的实现类。最终model将数据放到request域中
如果不是用@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将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括一个method方法。方法之行结束,形参数据销毁。
springmvc的controller开发类似于service开发
springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类似的成员变量接受参数,无法使用单例,只能使用多例。经过实际测试,struts2速度慢,在于实用struts标签,如果使用struts2建议使用jstl。
例如包装的pojo为UserQueryVo,页面的input标签的name要绑定到UserQueryVo的userCustom属性的username属性中,则input的name定义为userCustom.username,即<input type="text" name="userCustom.username">
例如:实现查看复选框选中的情况。
页面中复选框的name为c_name,value为String型的,则controller方法的形参定义为“String []c_name”,即页面的name与形参的name相同。
例如:批量修改用户信息。用户信息显示(input标签)在页面,手动修改并提交。
一般在封装的pojo类(如:UserQueryVo)中设置Link
在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.jarcommons-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相同RequestBody将json串转成java对象,ResponseBody将Java对象转换成json串
导入jar包 jackson-core.jarjackson-mapper-asl.jar配置json转换器
如果使用则不需配置如果使用了单独的处理器映射器,则需要在适配器中加入
<bean class="适配器"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> </list> </property></bean>新闻热点
疑难解答