SSM框架的整合(详细)
内容目录(点击可跳转)
一、添加SpringMVC框架支持
二、控制器和请求处理方法
三、返回和接收JSON数据
四、加入MyBatis框架
五、编写映射接口及SQL语句
六、拦截器
一、添加SpringMVC框架支持
下载网址:
http://maven.springframework.org/release/org/springframework/spring
1、为了省去在web.xml文件中配置DispatcherServlet,转为使用Java代码即可配置DispatcherServlet 的映射路径,Spring MVC提供了一个AbstractAnnotationConfigDispatcherServletInitializer抽象类,它实现了WebApplicationInitializer接口,可方便开发者进行SpringMVC和Spring的配置。该类中定义如下3个抽象方法:
Class<?>[] getRootConfigClasses(); //返回Spring IoC容器的Java配置类
Class<?>[] getServletConfigClasses(); //返回Spring MVC的Java配置类
String[] getServletMappings(); //返回DispatcherServlet映射的路径
如果要配置过滤器,可重写如下方法:
Filter[] getServletFilters() //返回自定义的过滤器
【示例】
public classDemoInitializerextendsAbstractAnnotationConfigDispatcherServletInitializer{
@Override
protectedClass<?>[]getRootConfigClasses(){
returnnewClass[]{AppConfig.class};
}
@Override
protectedClass<?>[]getServletConfigClasses(){
returnnull;
}
@Override
protectedString[]getServletMappings(){
returnnewString[]{"/"};
}
}
2、SpringIoC容器的配置:
(1)将@Configuration注解用在IoC容器配置类上。该类中带有@Bean注解的方法返回的对象会被注册到IoC容器中,方法名就是Bean的名字。
提示:使用@Configuration注解的类不能是final的,并且具有无参构造函数。
@Bean注解的属性:
@Bean(name={}, autowire=Autowire.NO, initMethod=“”, destroyMethod=“”)
(2)在配置类上添加@EnableWebMvc注解,该注解会自动注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
(3)添加@ComponentScan注解,扫描指定的包路径下面的带有@Controller、@Service、@Repository、@Component 的类。
可以不设置basePackages属性,则扫描当前包及其子包下的所有类。
【示例】
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.xxx.xxx")
publicclassAppConfig{
@Bean
publicViewResolverviewResolver(){
InternalResourceViewResolverviewResolver=newInternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
returnviewResolver;
}
}
(4) 如果针对Spring MVC有其它的配置,比如想配置拦截器、消息转换器等,这些Bean不能凭借类型或name就能被Spring MVC自动识别并使用,此时可以让配置类实现WebMvcConfigurer 接口。
WebMvcConfigurer接口中定义了一些方法方便我们进行相关配置。
通常重写如下方法:
addViewControllers(ViewControllerRegistry registry) //添加视图控制器
configureViewResolvers(ViewResolverRegistry registry) //配置视图解析器
configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
addResourceHandlers(ResourceHandlerRegistry registry)
追加视图控制器
视图控制器可以将指定的请求url映射到逻辑视图名,免除编写controller的麻烦。
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
注:”/login”是url路径;”login”是视图名。
配置视图解析器
重写configureViewResolvers(ViewResolverRegistry registry)方法。
参数ViewResolverRegistry 常用的几个方法:
jsp(String prefix,String suffix)方法会注册一个内部资源视图解析器,参数指定路径前缀和后缀,如:registry.jsp("/WEB-INF/jsp/", ".jsp");
beanName()会注册一个BeanNameViewResolver;
viewResolver(ViewResolver viewResolver)方法用来注册自定义的视图解析器。
二、控制器和请求处理方法
使用@Controller和@RequestMapping注解可将请求URL和控制器类中的方法进行关联。
示例:
@Controller
public class ProductController {
@RequestMapping(value = "/getProductCount")
public ModelAndView getProductCount() {
......
}
}
2.1 @RequestMapping注解
可以在控制器类上使用@RequestMapping限定来请求URL。
value属性值可使用{}将多个请求URL映射到一个处理方法上。如下:
@RequestMapping(value={"login", "test"})
可使用method属性限定请求的方式,如GET或POST。如下:
@RequestMapping(value = "login", method= RequestMethod.POST)
可使用params属性要求该请求必须提交指定的参数。如下:
@RequestMapping(value = "login", params="userId")
Spring4.3+引入了@GetMapping、@PostMapping注解。
@GetMapping是@RequestMapping(method = RequestMethod.GET)的缩写。
@PostMapping是@RequestMapping(method = RequestMethod.POST)的缩写。
2.2 获取客户端提交的参数
客户端提交的参数值可通过方法的形参来接收。
如果处理器方法形参名称和请求参数的名称相同,Spring MVC会自动进行类型转换并绑定到方法的形参上。
注意:如果客户端未提交同名参数,则形参将被赋值null,因此,形参最好使用包装器类型。
形参如果是日期类型,需要自定义类型转换器。
方法形参的类型也可是自定义类,Spring MVC将自动实例化它并装配客户端提交的参数值,要求该类中提供相应的set方法。
如果客户端提交了多个同名的参数,可使用数组类型或列表类型的形参。
如果客户端提交的参数名称和处理方法形参名称不同,可使用@RequestParam注解。
@RequestParam注解有如下属性:
value:请求参数的名称;
required:是否必须,默认是true,如果未提交该参数则返回400错误;
defaultValue:默认值,表示请求中如果没有该参数时使用的默认值。
publicString methodName(@RequestParam(value = “uId”) Integer id) {
}
处理器方法默认还支持以下形参类型:
HttpServletRequest
HttpServletResponse
HttpSession
Model/ModelMap
形参中如果有上面这些类型,spring mvc会自动绑定。
提示:Model是一个接口,ModelMap类实现了Model接口和Map接口。该参数的作用是将数据填充到request域,和ModelAndView中的Model对象功能类似。
另外,模型对象也会被自动放入Model对象中,对应的key为形参类型的简单名。
2.3处理器方法返回值的类型
ModelAndView
ModelAndView类包含两个属性:view和model。
view属性是通常是一个String类型的值,表示逻辑视图名称;
model属性是一个ModelMap类型的对象。
String
返回的字符串被看作逻辑视图名,此时方法中一般会设置ModelMap入参以便存储需传递的数据。
void
当处理器方法使用了HttpServletResponse参数,则Spring框架不做任何后续处理。
如果没有使用HttpServletResponse参数,则根据请求url进行视图解析,比如请求url为/sxt_demo/test,则将test作为逻辑视图名。
2.4 自定义转换器类
编写一个实现了Converter<S,T>接口的类并实现接口中规定的方法。
Converter<S,T>接口中定义的方法:
T convert(S source);
配置自定义的数据类型转换器:
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new MyDateConverter());
}
2.5 静态资源文件无法正常访问的解决方案:
配置:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
该配置是启用DefaultServletHttpRequestHandler来根据客户端请求寻找静态资源文件,默认从web根目录开始寻找,且文件不能位于WEB-INF下。
配置:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/**")
.addResourceLocations("/WEB-INF/static/");
}
这种配置方式则是添加了一个处理静态资源请求的Handler,它将从指定的路径开始寻找,可以是WEB-INF目录下。
三、返回和接收JSON数据
1、在控制器中的方法上加@ResponseBody注解就能将方法返回值转为JSON应答。
内部原理:该注解让SpringMVC跳过视图解析过程,由处理器适配器根据请求头的Accept值来选用适合的MessageConverter,将方法的返回值转换并写入应答流,返回给客户端。
2、客户端请求头的Accept值如果是:application/json,text/plain,处理器适配器就会使用JSON转换器将方法返回值转为JSON格式。
3、配置类上的@EnableWebMvc注解会根据项目类路径下是否存在com.fasterxml.jackson.databind.ObjectMapper等相关类,自动配置相应的消息转换器。
Jackson 版本要求2.2.0+包含3个jar包:
jackson-databind,
jackson-annotations,
jackson-core。
@RestController注解
将这个注解用在控制器类上,等效于类上使用了@Controller内部的方法上使用了@ResponseBody注解。
@RequestBody注解用在处理器方法的形参前面,如下:
public String saveInfo(@RequestBody ProductInfo prdInfo){
}
这时SpringMVC会根据请求头的Content-Type值,选择合适的消息转换器来转换请求正文的内容,并把转换后的结果绑定到参数上。
如果请求头Content-Type的值为application/x-www-form-urlencoded,则使用FormHttpMessageConverter进行转换,这种情况下,可以省略该注解。
如果请求头Content-Type的值为application/json,则使用JSON转换器进行转换,会把请求正文部分的JSON字符串转换为对象。
提示:如果执行文件上传(Content-Type的值为multipart/form-data),则不能使用@RequestBody注解。
四、加入MyBatis框架
拷贝mybatis-spring-1.3.2.jar包。
mybatis-spring-1.3.2.jar包中提供了如下两个辅助类,可用在Spring的配置文件中:
org.mybatis.spring.SqlSessionFactoryBean
//帮助创建SqlSessionFactory
org.mybatis.spring.mapper.MapperFactoryBean
//帮助创建映射器接口实例
首先配置数据源和事务管理器:
@Configuration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = Controller.class) })
@EnableTransactionManagement
public class SpringConfig {
@Bean(destroyMethod = "close")
public BasicDataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
…
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
PlatformTransactionManagertransactionManager=new
DataSourceTransactionManager(dataSource);
return transactionManager;}
}
配置SqlSessionFactory:
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
SqlSessionFactory factory = null;
try {factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:com/lintao/xx/*.mapper.xml"));
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("com.lintao.demo.beans");
org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(configuration);
factory = factoryBean.getObject();}
catch (Exception e) {}
return factory;
}
配置映射接口扫描器:
使用@MapperScan注解来扫描并创建映射器接口的实例。如下:
@Configuration
@MapperScan("com.lintao.xx.dao")
public class SpringConfig {
// ...
}
五、编写映射接口及SQL语句
1、查询相关的注解:
@Select(value=””)
@Results用来设置记录行与Bean对象的对应关系,其中包含多个@Result分别设置每个列的映射关系。
@ResultMap用来通过Id关联到对应的Results。
【示例】
@Select(value = “”)
@Results(value = { @Result(column = "user_id", property = "userId"),
@Result(column = "user_account", property = "account }, id = "rm1")
public UserInfo findByName(String name);
@Select(value = “")
@ResultMap(value="rm1")
public UserInfo findById(Integer id);
2、插入、更新和删除相关的注解
@Insert
@Options
【示例】
@Insert(value=“")
@Options(useGeneratedKeys=true,keyColumn="u_id",keyProperty="userId")
public int saveInfo(UserInfo userInfo);
@Update(“")
public int updateInfo(UserInfo userInfo);
@Delete(“")
public int deleteInfo(int userId);
3、复杂映射还是编写映射XML文件好一些
文档类型声明:
<!DOCTYPEmapperPUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
【示例】
<mappernamespace="com...UserMapper">
<selectid=""parameterType="_int"resultType="UserInfo">
<![CDATA[SELECT … FROM … WHERE id=#{id}]]>
</select>
……
</mapper>
注:
namespace属性值为映射器接口的完整类名;
SQL语句中的占位符使用#{}.
执行insert语句时,如果某些属性值可能为null,此时需要声明该属性对应列的jdbcType。
如下:
insert into userInfo(id,name,age,birthday) values(
#{id},
#{name},
#{age},
#{birthday,jdbcType=DATE}
)
jdbcType属性指明该列的类型。
jdbcType属性可取org.apache.ibatis.type.JdbcType的枚举值:
TINYINT; SMALLINT; INTEGER;
FLOAT; REAL; DOUBLE; NUMERIC; DECIMAL;
CHAR; VARCHAR; LONGVARCHAR;
DATE; TIMESTAMP;
BLOB; CLOB;
BOOLEAN;
NCHAR; NVARCHAR
六、拦截器
自定义拦截器需要实现org.springframework.web.servlet.HandlerInterceptor接口。
该接口中定义了如下方法:
publicinterfaceHandlerInterceptor{
booleanpreHandle(HttpServletRequestreq,HttpServletResponseresp,Objecthandler);
voidpostHandle(HttpServletRequestreq,HttpServletResponseresp,Objecthandler,ModelAndViewmav);
voidafterCompletion(HttpServletRequestreq,HttpServletResponseresp,Objecthandler,Exceptionex);
}
preHandle:预处理方法,在目标处理方法之前被执行。第三个参数handler为处理器对象。
返回true表示继续流程;返回false表示不再继续执行后续的拦截器或处理器方法,这种情况下通常要借助response自行给客户端返回应答内容;此后仅调用它之前拦截器的afterCompletion方法;
postHandle:后处理方法,在处理器方法之后,但在渲染视图之前被执行。此时可以通过modelAndView参数对象对模型数据进行修改或对视图进行修改,modelAndView也可能为null。
afterCompletion:视图渲染完毕后被回调,可以进行一些资源清理。
只有preHandle方法返回true的拦截器它的afterCompletion会被执行。
假设有两个拦截器Interceptor1和Interceptor2,则其正常流程如下:
Interceptor1.preHandle() 返回true
Interceptor2.preHandle() 返回true
HandlerApapter
Interceptor2.postHandle()
Interceptor1.postHandle()
渲染View
Interceptor2.afterCompletion()
Interceptor1.afterCompletion()
如果Interceptor2返回false,则其流程如下:
Interceptor1.preHandle() 返回true
Interceptor2.preHandle() 返回false
Interceptor1.afterCompletion()
配置:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/admin/**");
}