spring整合mybatis
对于spring项目中整合mybatsi前置条件:导入spring本身的依赖,以及mybatis的依赖,还需要多导入一个整合mybatis与spring的依赖(mybatis提供的)。
1、导入依赖:spring-context spring-jdbc mybatis-spring mybatis mysql-connector-java druid lombok
2、编写spring的配置文件
a)扫描包下的注解(spring本身的注解)
b)配置数据库连接池(druid)
c)SqlSessionFactoryBean(注入一个datasource)
d)MapperScannerConfigurer 指定扫描的包(basepackage:扫描创建mapper接口的代理对象)
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.woniuxy"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///bank?characterEncoding=utf-8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--
配置sqlSessionFactoryBean
作用:产生一个sqlsessionfactory 只要ioc容器中有任何一个bean需要使用sqlsession,
那么就会由sqlsessionfactory自动创建一个给其使用。
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- <property name="configLocation" value="classpath:sqlConfig.xml"/>-->
</bean>
<!--
配置MapperScannerConfigurer:
作用:用于扫描指定的包,创建对应接口的代理对象
-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.woniuxy.mapper"/>
</bean>
</beans>
spingmvc
mvc: m model v view c controller
Spring MVC 的请求流程:
入门案例的实现
1、导入依赖,如果配置dispatcherServlet报错,再导入servlet-api依赖即可
<!--1、springmvc的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
2、配置前端控制器dispatcherServlet
<!--2、配置DispatcherServlet-->
<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>/</url-pattern>
</servlet-mapping>
3、编写控制器
/**
* controller就相当于web项目中的servlet,用于接收请求,作出响应
*/
@Controller
public class UserController {
// http://localhost:8080/hello
@RequestMapping("/hello")
public String hello(){
System.out.println("hello springmvc");
return "main";//逻辑视图名
}
}
4、编写springmvc配置文件
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描@Controller注解-->
<context:component-scan base-package="com.woniuxy.controller"/>
<!--配置springmvc的三大组件-->
<!--配置映射器处理器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--配置映射器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- main -> /main.jsp -->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
springmvc静态资源映射
当dispatcherservlet的url-pattern设置的是”/“,拦截所有请求,此时需要对项目中的静态资源进行放行,否则访问不到。
使用mvc:resources标签进行静态资源的放行设置。
<!--
静态资源映射
http://localhost:8080/css/main.css
mapping:用于匹配请求的url中的内容
location:用于指定一个项目中的路径
-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/html/**" location="/html/"/>
自定义类型转换器
当spring提供的类型转换器不足以解决请求参数中传递的参数值的时候,需要使用自定义类型转换器。
1、自定义转换器需要实现一个converter接口 S:要被转换的类型 T:转换之后得到的类型
public class String2Date implements Converter<String, Date> {
@Override
public Date convert(String source) {
Date date=null;
if (StringUtils.hasLength(source)) {
//使用simpleDateFormat对当前字符串进行转换即可。
//yyyy-MM-dd
//yyyy/MM/dd
String pattern1="[0-9]{4}-[0-9]{2}-[0-9]{2}";
String pattern2="[0-9]{4}/[0-9]{2}/[0-9]{2}";
try {
if (source.matches(pattern1)) {
date=new SimpleDateFormat("yyyy-MM-dd").parse(source);
}
if (source.matches(pattern2)) {
date=new SimpleDateFormat("yyyy/MM/dd").parse(source);
}
} catch (ParseException e) {
e.printStackTrace();
}
}else{
//被转换的字符串为空时,进行自定义的处理。
throw new RuntimeException("参数为空");
}
return date;
}
}
2、将自定义的类型转换器添加到spring提供的类型转换器集合中
<!--配置自定义的类型转换器:conversionServiceFactoryBean-->
<bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.woniuxy.converter.MyConverter"/>
</set>
</property>
</bean>
3、将修改过后的conversionService2重新注册到spring中。
<!--spring3.1.*以上版本中,使用了 <mvc:annotation-driven/>
替换了RequestMappingHandlerMapping和RequestMappingHandlerAdapter
<mvc:annotation-driven>会自动注册RequestMappingHandlerMapping
与RequestMappingHandlerAdapter两个Bean,
conversion-service:将变更后的conversionService重新注册给spring
-->
<mvc:annotation-driven conversion-service="conversionService2"/>
请求参数映射
1、简单类型的请求参数映射(String 和 基本数据类型)
需要注意的是:请求参数的名称必须和控制器方法的形参名称保持一致,否则注入不了。
<form action="/user/login" method="post">
用户名:<input type="text" name="username" value="tom"><br>
密码:<input type="text" name="password" value="111"><br>
<input type="submit" value="登录" id="btn">
</form>
//请求参数映射:基本数据类型和String,直接就进行转换并注入到控制器的方法形参中
//要求:方法的形参名必须和请求参数的名称保持一致,否则无法注入
@RequestMapping("/user/login")
public String login(User user){
System.out.println(user);
return "index";
}
2、同名参数的映射
<input type="checkbox" name="hobbies" value="eat">吃饭
<input type="checkbox" name="hobbies" value="sleep">睡觉
<input type="checkbox" name="hobbies" value="watch tv">看电视
@RequestMapping("/login")
public String login(String[] hobbies){
System.out.println(hobbies.length);
return "index";
}
或
@RequestMapping("/login")
public String login(@RequestParam ArrayList<String> hobbies){
System.out.println(hobbies);
return "index";
}
3、javaBean接收请求参数
要求:javaBean的成员变量名必须和请求参数名称保持一致
<form action="/user/login" method="post">
用户名:<input type="text" name="username" value="tom"><br>
密码:<input type="text" name="password" value="111"><br>
<input type="submit" value="登录" id="btn">
</form>
@Data
public class User {
String username;
String password;
}
4、ajax传递的参数
4.1 传递JSON对象时,与普通参数传递没有区别
var form={
username:$("#username").val(),
password:$("#password").val()
}
$.ajax({
url:"/user/realLogin",
data:form,
type:"post",
dataType:"json",
success:function (resp) {
alert(resp)
}
})
@RequestMapping("/realLogin")
public String realLogin(User user){
System.out.println(1111);
System.out.println(user);
return "";
}
4.2 传递json字符串,要求是一个标准的json字符串
如果传递的是json字符串,
请求方式必须是post
请求的内容类型必须是 contentType:”application/json;charset=utf-8”
后台接收时必须使用@RequestBody
springmvc使用jackson来解析json字符串,所以必须导入相应的三个依赖。
jackson-core jackson-annotations jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.5</version>
</dependency>
var form={
username:$("#username").val(),
password:$("#password").val()
}
//以json字符串的方式向后台传递参数
//1、请求方式必须是post
//2、请求的内容类型必须是 contentType:"application/json;charset=utf-8"
//3、后台接收时必须使用@RequestBody 只能使用一个
//4、springmvc使用jackson来解析json字符串,所以必须导入相应的三个依赖。
//jackson-core jackson-annotations jackson-databind
form=JSON.stringify(form)
$.ajax({
url:"/user/realLogin",
data:form,
contentType:"application/json;charset=utf-8",
type:"post",
dataType:"json",
success:function (resp) {
alert(resp)
}
})
@RequestMapping("/realLogin")
public String realLogin(@RequestBody User user){
System.out.println(1111);
System.out.println(user);
return "";
}
路径传参
restful风格的路径传参:http://localhost:8080/login/tom/111 参数存在于路径中。
不是路径传参:http://localhost:8080/login?username=tom&password=111
1、在@RequestMapping注解完整映射路径 /login/{username}/{password}
2、在参数上加@PathVariable注解
@RequestMapping("testRestFul/{username}/{password}")
public String testRestFul(@PathVariable String username,@PathVariable String password){
System.out.println(username+":"+password);
return "redirect:/html/main.html";
}
注意:使用路径传参,不能再使用javaBean的形式进行参数注入。
servletAPI的获取
@RequestMapping("testServletApi")
public String testServletApi(HttpServletRequest request, HttpSession session){
System.out.println(request);
System.out.println(session);
System.out.println(session.getServletContext());
return "redirect:/html/main.html";
}
注意:servletcontext是无法注入的
响应返回值
string:
//响应回去的类型:String :逻辑视图名 物理视图(forward:请求转发 redirect:重定向)
//String
//逻辑视图名:一定配置视图解析器
//物理视图:forward redirect关键字来实现直接的跳转。
//也可以使用forward 或redirect 关键字实现控制器方法的跳转
//ajax请求: JS域中发出来的 @responseBody
逻辑视图名:
@RequestMapping("/login")
public String login(ArrayList<String> hobbies){
System.out.println(hobbies);
return "index";
}
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".html"/>
</bean>
物理视图
默认请求转发,forward关键字可以省略不写
//http://localhost:8080/user/testForward
@RequestMapping("testForward")
public String testForward(){
System.out.println("请求转发");
//return "/html/main.html";
return "forward:/html/main.html";
}
重定向
//http://localhost:8080/user/testRedirect
@RequestMapping("testRedirect")
public String testRedirect(){
System.out.println("重定向");
return "redirect:/html/main.html";
}
控制器方法内部跳转
//http://localhost:8080/user/testRedirect
@RequestMapping("testRedirect")
public String testRedirect(){
System.out.println("重定向");
return "redirect:toLogin";
}
@RequestMapping("toLogin")
public String toLogin(){
System.out.println("重定向");
return "redirect:/html/main.html";
}
ajax请求: JS域中发出来的 @responseBody
$(function () {
$("#btn").click(function () {
$.ajax({
url:"/user/login",
data:$("#myForm").serialize(),
dataType:"json",
type:"post",
success:function (resp) {
console.log(resp)
}
})
})
})
@RequestMapping("login") //http://localhost:8080/user/login?username=tom&password=111
@ResponseBody
public String login(String username,String password){
System.out.println(username+":"+password);
// return "redirect:/html/main.html";
// return "{\"msg\":\"success\"}";
return new JSONObject().toJSONString("success");
}
void(了解)
如果控制器方法无返回值时,会自动将请求路径中的requestMapping部分作为逻辑视图名进行相应的跳转,如果没有视图解析器,会报错,在项目中必须存在与逻辑名对应的物理视图才可以正常访问,否则404。
object 给ajax用 @ResponseBody
//Object
//http://localhost:8080/user/getUser?username=tom&password=111
@RequestMapping("getUser")
@ResponseBody
//一定需要统一返回给前端的格式 dto处理 data transfer object
public User getUser(User user){
System.out.println(user);
return user;
}
统一返回给前端的数据格式 dto
dto: data transfer object
自定义一个dto
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
private Boolean flag;//当前端发起调用时,告诉前端此次调用实现的功能是否成功
private String code;//自定义的响应状态码
private String message;//封装返回给前端的消息
private T data;//用于封装返回给前端的真实数据
}
@RequestMapping("findAll")
@ResponseBody
public Result findAll(){
//执行了某个业务,返回一个用户数据的集合
List<User> users= Arrays.asList(new User("tom","111"),new User("jack","222"));
return new Result(true, StatusCode.OK,"查询用户数据成功",users);
}
ModelAndView
spring提供的一个对象,可用该对象向对应的域中存储数据(model),也可使用该对象设置对应的视图(view)
//ModelAndView model模型 view视图
@RequestMapping("testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mv = new ModelAndView();
mv.addObject("user",new User("tom","111"));//向model中保存数据
mv.setViewName("/html/main.html");//设置视图名称
return mv;
}
注意的是:数据存放在request域中,如果不使用模板,是无法取得保存的数据的。
如果是前后端分离的项目,不会再使用此种方式。
restful风格的接口设计
实际项目开发中,目前基本上使用的都是前后端分离的技术,前端ajax发送rest时,后台应对应的使用restful风格去进行接口设计。
restful风格的接口设计
* 后台使得rest请求方式进行接口设计
* rest: GET POST PUT DELETE
* GET 查询
* POST 新增
* PUT 修改
* DELETE 删除
*
* restful风格的接口设计:在requestmapping中不应该出现动词
*
* 幂等性:面试的时候可能被问到
* 对同一个接口的相同操作,结果应该相同
* 只有POST请求不是幂等性的,其余的GET\PUT\DELETE都是幂等性的。
@Controller
public class RestFulController {
@RequestMapping(value="user",method= RequestMethod.GET)
public String find(){
System.out.println("执行了find操作");
return "redirect:/html/main.html";
}
@RequestMapping(value = "user",method = RequestMethod.POST)
public String save(){
System.out.println("执行了save操作");
return "redirect:/html/main.html";
}
@RequestMapping(value = "user",method = RequestMethod.PUT)
public String update(){
System.out.println("执行了update操作");
return "redirect:/html/main.html";
}
@RequestMapping(value = "user",method = RequestMethod.DELETE)
public String delete(){
System.out.println("执行了delete操作");
return "redirect:/html/main.html";
}
}
测试时,可以使用postman或者发送$.ajax({type:GET|POST|PUT|DELETE}),也可以使用idea提供的测试工具
tools->http client->test restful web service
异常
自定义异常处理器
实现一个handlerExceptionResolver接口,注意,自定义异常处理器只要注册到容器中,会自动生效。
/**
* 自定义异常处理器
*/
@Component
public class CustomerExceptionHandler implements HandlerExceptionResolver {
@Override
publ
+-ic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//看看用户发送的请求是否是ajax请求,如果是,处理的方式一定和普通形式的请求是不一样的。
ModelAndView mv = new ModelAndView();
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
//ajax请求
//创建json视图,使用的是fastJson
FastJsonJsonView jsonView = new FastJsonJsonView();
HashMap<String, Object> map = new HashMap<>();
map.put("message","服务器繁忙");
jsonView.setAttributesMap(map);
mv.setView(jsonView);
}else{
mv.setViewName("/html/error.html");
}
return mv;
}
}
全局异常总类
@RestControllerAdvice
public class GlobalExceptionHandler {
//全局异常总类中的编写规则:
// 一定会有一个处理Exception类的方法兜底
// 在异常总类中,对某一个具体的异常进行处理。
@ExceptionHandler(NullPointerException.class)
public Result handlerNullPointException(){
return new Result(false,"20002","空指针异常",null);
}
@ExceptionHandler(ArithmeticException.class)
public Result handlerArithmeticException(){
return new Result(false,"20003","算术异常",null);
}
@ExceptionHandler(Exception.class)
public Result handlerException(){
return new Result(false,"20001","服务器异常",null);
}
}
使用@RestController代替@Controller和@ResponseBody
//使用了@RestController注解,一定没有办法进行页面跳转。
在使用restful风格进行接口设计时
使用@(Get|Post|Put|Delete)Mapping代替@RequestMapping(value=”user”,method= RequestMethod.GET|POST|PUT|DELETE)
参数校验
对于提交到后台的参数,会做两步验证:第一步验证发生在前端表单提交时,第二步验证发生在后台参数注入的时候。
JSR303方式进行的参数校验,官方推荐的实践:hibernate-validator
导入依赖
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
控制器方法中使用javaBean来接收请求参数,在javaBean的成员变量上使用对应的注解,来对注入的参数值进行校验。
@Data
public class User {
@NotNull(message = "用户名不能为空")
@Length(min = 10,max = 16,message = "用户名长度必须在10-16之间")
@Pattern(regexp = "[a-zA-Z]\\w+",message = "用户名不能以数字开头")
private String username;
@NotNull(message = "密码不能为空")
@Length(min = 6,max = 8,message = "长度只能在6-8之间")
private String password;
@NotNull(message = "邮箱不能为空")
@Pattern(regexp= "\\w{1,15}@\\w{1,15}(.\\w{2,3}){1,2}",message = "邮箱格式不正确")
private String email;
}
控制器中使用@valid注解对参数注入的值进行校验,校验结果保存在bindingResult中,请注意:bindingResult只能紧跟在要校验的对象之后。
@PostMapping
@ResponseBody
public Result register(@Valid User user, BindingResult bindingResult) throws ParameterValidetorException {
//判断验证结果中,是否有错误,如果有错误,意味着参数验证没通过
if (bindingResult.hasErrors()) {
throw new ParameterValidetorException();
}
System.out.println(user);
return new Result(true, StatusCode.OK,"注册成功",null);
}
拦截器
拦截器是springmvc中一个强大的控件,它的功能有点类似于过滤器。拦截器的作用时期是在前端控制器(dispatcherservlet)和被@Controller注解的控制器之间。
在springmvc中,如果要创建拦截器,需要实现一个接口:handlerInterceptor。实现业务时,主要关注:preHandle(),此方法决定是请求是否能向下一步进入到controller中。
步骤1:创建拦截器
/**
* 只要实现了HandlerInterceptor接口,当前类就会是一个拦截器
*/
public class FirstInterceptor implements HandlerInterceptor {
/**
* 前置处理:在业务控制器方法执行之前执行的
* 根据preHandle方法的返回值,决定是否放行 true 放行 false 拦截
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor的preHandle执行了");
//放行
return true;
}
/**
* 后置处理:在控制器方法执行之后再执行的
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor的postHandle执行了");
}
/**
* 渲染视图完成之后执行的
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor的afterCompletion执行了");
}
}
步骤2:配置拦截器
<!--开启拦截器配置-->
<mvc:interceptors>
<!--配置某个拦截器,该配置可以有多个-->
<mvc:interceptor>
<!--mvc:mapping:用于配置被拦截器拦截的请求资源 黑名单 -->
<mvc:mapping path="/**"/>
<!--mvc:exclude-mapping:用于配置不被拦截器拦截的请求资源 白名单 -->
<mvc:exclude-mapping path="/"/>
<mvc:exclude-mapping path="/user/login"/>
<mvc:exclude-mapping path="/user/register"/>
<mvc:exclude-mapping path="/html/login.html"/>
<mvc:exclude-mapping path="/html/register.html"/>
<mvc:exclude-mapping path="/css/*"/>
<mvc:exclude-mapping path="/js/*"/>
<mvc:exclude-mapping path="/images/*"/>
<!--配置使用哪个拦截器来处理被拦截的资源-->
<bean class="com.woniuxy.interceptor.FirstInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器链的执行顺序由配置文件中的拦截器配置顺序来决定。
拦截器应用 登录验证
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录验证
//判断session中是保存了登录状态
Object loginUser = request.getSession().getAttribute("loginUser");
if (ObjectUtils.isEmpty(loginUser)) {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("当前用户尚未登录");
//拦截
return false;
}
return true;
}
}
<!--开启拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/"/>
<mvc:exclude-mapping path="/user/login"/>
<mvc:exclude-mapping path="/user/register"/>
<mvc:exclude-mapping path="/html/login.html"/>
<mvc:exclude-mapping path="/html/register.html"/>
<mvc:exclude-mapping path="/css/*"/>
<mvc:exclude-mapping path="/js/*"/>
<mvc:exclude-mapping path="/images/*"/>
<bean class="com.woniuxy.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
ssm整合 (spring springmvc mybatis)
整合时如果不考虑父子容器的问题,就一定导致一个后果:声明式事务失效。
父子容器
让spring扫描service
让springmvc扫描controller
整合实现
spring整合mybatis
与之前的配置一样。
spring整合springmvc
1、web.xml配置,让web容器启动时先创建父容器,后创建子容器。
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--加载类路径下的xml文件创建父容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--监听servletContext对象的创建-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 创建dispatcherservlet时,创建子容器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<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>/</url-pattern>
</servlet-mapping>
</web-app>
2、配置spring和springmvc各自扫描的包
让spring扫描service
<context:component-scan base-package="com.woniuxy.service"/>
让springmvc扫描controller
<context:component-scan base-package="com.woniuxy.controller"/>
此时整合即已完成。
SSM整合及声明式事务:
applicationContext.xml spring配置
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.woniuxy.service"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///bank?characterEncoding=utf-8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--
配置sqlSessionFactoryBean
作用:产生一个sqlsessionfactory 只要ioc容器中有任何一个bean需要使用sqlsession,
那么就会由sqlsessionfactory自动创建一个给其使用。
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- <property name="configLocation" value="classpath:sqlConfig.xml"/>-->
</bean>
<!--
配置MapperScannerConfigurer:
作用:用于扫描指定的包,创建对应接口的代理对象
-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.woniuxy.mapper"/>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 对声明式事务的注解提供支持 -->
<tx:annotation-driven/>
</beans>
springmvc.xml springmvc配置
<?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: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.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.woniuxy.controller"/>
<mvc:annotation-driven/>
<!-- <mvc:resources mapping="/js/**" location="/js/"/>-->
<mvc:resources mapping="/html/**" location="/html/"/>
</beans>
数据访问层
public interface AccountMapper {
@Select("select * from account where username=#{username}")
Account findByUserName(String username);
@Update("update account set balance=#{balance} where username=#{username}")
int updateAccount(Account account);
}
业务层
@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {
@Resource
private AccountMapper accountMapper;
@Override
public void transfer(TransferVo transferVo){
//查询要进行转帐操作的两个人的帐户信息
Account sourceAccount = accountMapper.findByUserName(transferVo.getSource());
Account targetAccount = accountMapper.findByUserName(transferVo.getTarget());
//判断被转出人的帐户余额是否足够
if (sourceAccount.getBalance()>transferVo.getMoney()) {
//真正执行转账操作
sourceAccount.setBalance(sourceAccount.getBalance()-transferVo.getMoney());
targetAccount.setBalance(targetAccount.getBalance()+transferVo.getMoney());
accountMapper.updateAccount(sourceAccount);
System.out.println(1/0);
accountMapper.updateAccount(targetAccount);
}
}
}
控制层
@Controller
public class AccountController {
@Resource
private AccountService accountService;
@RequestMapping("account/transfer")
@ResponseBody
public Result transfer(TransferVo transferVo){
accountService.transfer(transferVo);
return new Result(true, StatusCode.OK,"转账成功",null);
}
}