0X0a SpringMVC简介
1、什么是MVC
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分
M:Model,模型层,指工程中的JavaBean,作用是处理数据
JavBean分为两类:
* 一类称为实体类Bean:专门存储业务数据,比如Student、User类等等
* 一类称为业务处理Bean:指Service或者Dao对象,专门用于处理业务逻辑和数据访问
V:View,视图层,指工程中的html或者jsp等页面,作用是与用户进行交互,展示数据
C:Controller,控制层,指工程中servlet,作用是接受请求和响应浏览器
MVC的工作流程:
用户通过视图层发送请求到服务器,在服务期中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器。
2、什么是SpringMVC
SpringMVC是Spring的后续产品,是Spring的一个子项目
[注] 三层架构分为表述层、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
3、SpringMVC的特点
1、Spring家族原生产品
2、基于原生的Servlet
3、代码清新简洁
4、性能卓越
0X0b 入门案例
1、目录结构(以Maven的web创建)
2、详细代码
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext ( ) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext ( ) ;
context. register ( SpringMvcConfig . class ) ;
return context;
}
protected String [ ] getServletMappings ( ) {
return new String [ ] { "/" } ;
}
protected WebApplicationContext createRootApplicationContext ( ) {
return null ;
}
}
@Configuration
@ComponentScan ( "com.company.controller" )
public class SpringMvcConfig {
}
@Controller ( "userController" )
public class UserController {
@RequestMapping ( "/save" )
@ResponseBody
public String save ( ) {
System . out. println ( "user save..." ) ;
return "{'info':'SpringMVC'}" ;
}
}
<?xml version="1.0" encoding="UTF-8"?>
< project xmlns = " http://maven.apache.org/POM/4.0.0"
xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0.0</ modelVersion>
< groupId> org.example</ groupId>
< artifactId> SpringMVC</ artifactId>
< version> 1.0-SNAPSHOT</ version>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 3.1.0</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.2.10.RELEASE</ version>
</ dependency>
</ dependencies>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat7-maven-plugin</ artifactId>
< version> 2.2</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
3、Bean加载规则
在项目中会出现Spring的项目(dao和service),因此有Spring扫描,但是Spring不能扫描SpringMVC的项目文件(controller),因此我们需要对config的配置进行修改
@Configuration
@ComponentScan ( { "com.company.dao" , "com.company.service" } )
public class SpringConfig {
}
@Configuration
@ComponentScan ( value = "com.company" ,
excludeFilters = @ComponentScan.Filter (
type = FilterType . ANNOTATION,
classes = Controller . class
)
)
public class SpringConfig {
}
0X0b 入门案例
1、请求映射路径
@RequestMapping
可以加载在方法上,也可以加载在类上
如果设置在类上,则为统一设置当前控制器方法请求访问路径
@Controller ( "userController" )
@RequestMapping ( "/user" )
public class UserController {
@RequestMapping ( "/save" )
@ResponseBody
public String save ( ) {
System . out. println ( "user save..." ) ;
return "{'info':'SpringMVC'}" ;
}
@RequestMapping ( "/delete" )
@ResponseBody
public String save ( ) {
System . out. println ( "user delete..." ) ;
return "{'info':'SpringMVC'}" ;
}
}
2、get请求和post请求
@Controller ( "userController" )
public class UserController {
@RequestMapping ( "/save" )
@ResponseBody
public String save ( String name, int age) {
System . out. println ( "name : " + name + ", age : " + age) ;
return "{'info':'SpringMVC'}" ;
}
}
@Override
protected Filter [ ] getServletFilters ( ) {
CharacterEncodingFilter filter = new CharacterEncodingFilter ( ) ;
filter. setEncoding ( "UTF-8" ) ;
return new Filter [ ] { filter} ;
}
3、参数传递
@Controller ( "userController" )
public class UserController {
@RequestMapping ( "/saveDifferentName" )
@ResponseBody
public String saveDifferentName ( @RequestParam ( "username" ) String name, int age) {
System . out. println ( "name : " + name + ", age : " + age) ;
return "{'info':'SpringMVC'}" ;
}
@RequestMapping ( "/savepojo" )
@ResponseBody
public String saveDifferentName ( User user) {
System . out. println ( "pojo传参" + user) ;
return "{'info':'SpringMVC'}" ;
}
}
4、json传参
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.0</ version>
</ dependency>
@Configuration
@ComponentScan ( "com.company.controller" )
@EnableWebMvc
public class SpringMvcConfig {
}
@Controller ( "userController" )
public class UserController {
@RequestMapping ( "/saveJson" )
@ResponseBody
public String saveJson ( @RequestBody List < String > likes) {
System . out. println ( "list(json)传参" + likes) ;
return "{'info':'SpringMVC'}" ;
}
@RequestMapping ( "/saveJsonPojo" )
@ResponseBody
public String saveJsonPojo ( @RequestBody User user) {
System . out. println ( "Pojo(json)传参" + user) ;
return "{'info':'SpringMVC'}" ;
}
}
5、响应
@Controller ( "userController" )
public class UserController {
@RequestMapping ( "/toJumpPage" )
public String toJumpPage ( ) {
System . out. println ( "跳转页面" ) ;
return page. jsp;
}
@RequestMapping ( "/toText" )
@ResponseBody
public String toText ( ) {
System . out. println ( "返回纯文本数据" ) ;
return "response text" ;
}
@RequestMapping ( "/toJsonPojo" )
@ResponseBody
public User toJsonPojo ( ) {
System . out. println ( "返回json对象数据" ) ;
User user = new User ( ) ;
user. setName ( "SpringMVC" ) ;
user. setAge ( 15 ) ;
return user;
}
}
0X0c REST风格
1、简介
表现形式状态转换
优点:隐藏了资源的访问行为,无法通过地址得知对应的资源是何种操作
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
2、RESTful入门案例
@RestController
@RequestMapping ( "/books" )
public class BookController {
@PostMapping
public String save ( @RequestBody Book book) {
System . out. println ( "book save..." + book) ;
return "{'module':'book save'}" ;
}
@DeleteMapping ( "/{id}" )
public String delete ( @PathVariable Integer id) {
System . out. println ( "book delete..." + id) ;
return "{'module':'book delete'}" ;
}
@PutMapping
public String update ( @RequestBody Book book) {
System . out. println ( "book update..." + book) ;
return "{'module':'book update'}" ;
}
@GetMapping ( "/{id}" )
public String getById ( @PathVariable Integer id) {
System . out. println ( "book getById..." + id) ;
return "{'module':'book getById'}" ;
}
@GetMapping
public String getAll ( ) {
System . out. println ( "book getAll..." ) ;
return "{'module':'book getAll'}" ;
}
}
3、页面交互数据时注意
由于我们在ServletContainersInitConfig里配置所有路由均走SpringMVC,因此某些静态路由无法访问
因此某些静态路由我们需要交给tomcat来处理
添加新的配置类
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers ( ResourceHandlerRegistry registry) {
registry. addResourceHandler ( "/pages/**" ) . addResourceLocations ( "/pages/" ) ;
registry. addResourceHandler ( "/js/**" ) . addResourceLocations ( "/js/" ) ;
registry. addResourceHandler ( "/css/**" ) . addResourceLocations ( "/css/" ) ;
registry. addResourceHandler ( "/plugins/**" ) . addResourceLocations ( "/plugins/" ) ;
}
}
0X0d SSM整合
1、表现层和前端数据传输数据协议
前端接收数据格式——创建结果模型类,封装数据到data属性中
前端接收数据格式——封装操作结果到code属性中
前端接收数据格式——封装特殊消息到message(msg)属性中
2、异常处理器
所有异常均抛出到表现层进行处理
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler ( Exception . class )
public Result doException ( Exception ex) {
return new Result ( null , null , "Exception" ) ;
}
}
3、项目异常分类
业务异常
规范的用户行为产生的异常 不规范的用户行为操作产生的异常 系统异常
其他异常
4、代码详细
结构目录
public class JdbcConfig {
@Value ( "${jdbc.driver}" )
private String driver;
@Value ( "${jdbc.url}" )
private String url;
@Value ( "${jdbc.username}" )
private String username;
@Value ( "${jdbc.password}" )
private String password;
@Bean
public DataSource dataSource ( ) {
DruidDataSource dataSource = new DruidDataSource ( ) ;
dataSource. setDriverClassName ( driver) ;
dataSource. setUrl ( url) ;
dataSource. setUsername ( username) ;
dataSource. setPassword ( password) ;
return dataSource;
}
@Bean
public PlatformTransactionManager platformTransactionManager ( DataSource dataSource) {
DataSourceTransactionManager ds = new DataSourceTransactionManager ( ) ;
ds. setDataSource ( dataSource) ;
return ds;
}
}
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory ( DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean ( ) ;
factoryBean. setDataSource ( dataSource) ;
factoryBean. setTypeAliasesPackage ( "com.company.domain" ) ;
return factoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer ( ) {
MapperScannerConfigurer msc = new MapperScannerConfigurer ( ) ;
msc. setBasePackage ( "com.company.dao" ) ;
return msc;
}
}
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class < ? > [ ] getRootConfigClasses ( ) {
return new Class [ ] { SpringConfig . class } ;
}
protected Class < ? > [ ] getServletConfigClasses ( ) {
return new Class [ ] { SpringMvcConfig . class } ;
}
protected String [ ] getServletMappings ( ) {
return new String [ ] { "/" } ;
}
}
@Configuration
@ComponentScan ( "com.company.service" )
@PropertySource ( "classpath:jdbc.properties" )
@Import ( { JdbcConfig . class , MybatisConfig . class } )
@EnableTransactionManagement
public class SpringConfig {
}
@Configuration
@ComponentScan ( "com.company.controller" )
@EnableWebMvc
public class SpringMvcConfig {
}
@RestController
@RequestMapping ( "/books" )
public class BookController {
@Autowired
private BookService bookService;
@PostMapping
public Result save ( @RequestBody Book book) {
boolean flag = bookService. save ( book) ;
return new Result ( flag ? Code . SAVE_OK : Code . SAVE_ERR, flag) ;
}
@PutMapping
public Result update ( @RequestBody Book book) {
boolean flag = bookService. update ( book) ;
return new Result ( flag ? Code . UPDATE_OK : Code . UPDATE_ERR, flag) ;
}
@DeleteMapping ( "/{id}" )
public Result delete ( @PathVariable Integer id) {
boolean flag = bookService. delete ( id) ;
return new Result ( flag ? Code . DELETE_OK : Code . DELETE_ERR, flag) ;
}
@GetMapping ( "/{id}" )
public Result getById ( @PathVariable Integer id) {
Book book = bookService. getById ( id) ;
Integer code = book != null ? Code . GET_OK : Code . GET_ERR;
String msg = book != null ? "" : "数据查询失败,请重试" ;
return new Result ( code, book, msg) ;
}
@GetMapping
public Result getAll ( ) {
List < Book > bookList = bookService. getAll ( ) ;
Integer code = bookList != null ? Code . GET_OK : Code . GET_ERR;
String msg = bookList != null ? "" : "数据查询失败,请重试" ;
return new Result ( code, bookList, msg) ;
}
}
public class Code {
public static final Integer SAVE_OK = 20011 ;
public static final Integer DELETE_OK = 20021 ;
public static final Integer UPDATE_OK = 20031 ;
public static final Integer GET_OK = 20041 ;
public static final Integer SAVE_ERR = 20010 ;
public static final Integer DELETE_ERR = 20020 ;
public static final Integer UPDATE_ERR = 20030 ;
public static final Integer GET_ERR = 20040 ;
}
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler ( SystemException . class )
public Result doSystemException ( SystemException ex) {
return new Result ( ex. getCode ( ) , null , ex. getMessage ( ) ) ;
}
@ExceptionHandler ( BusinessException . class )
public Result doBusinessException ( BusinessException ex) {
return new Result ( ex. getCode ( ) , null , ex. getMessage ( ) ) ;
}
@ExceptionHandler ( Exception . class )
public Result doException ( Exception ex) {
return new Result ( 666 , null , "系统繁忙,请稍后再试" ) ;
}
}
public class Result {
private Object data;
private Integer code;
private String msg;
public Result ( ) {
}
public Result ( Integer code, Object data) {
this . data = data;
this . code = code;
}
public Result ( Integer code, Object data, String msg) {
this . data = data;
this . code = code;
this . msg = msg;
}
public Object getData ( ) {
return data;
}
public void setData ( Object data) {
this . data = data;
}
public Integer getCode ( ) {
return code;
}
public void setCode ( Integer code) {
this . code = code;
}
public String getMsg ( ) {
return msg;
}
public void setMsg ( String msg) {
this . msg = msg;
}
}
public interface BookDao {
@Insert ( "insert into tb_book (type,name,description) values (#{type}, #{name}, #{description})" )
public void save ( Book book) ;
@Update ( "update tb_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}" )
public void update ( Book book) ;
@Delete ( "delete from tb_book where id = #{id}" )
public void delete ( Integer id) ;
@Select ( "select * from tb_book where id = #{id}" )
public Book getById ( Integer id) ;
@Select ( "select * from tb_book" )
public List < Book > getAll ( ) ;
}
public class Book {
private Integer id;
private String type;
private String name;
private String description;
@Override
public String toString ( ) {
return "Book{" +
"id=" + id +
", type='" + type + '\'' +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}' ;
}
public Integer getId ( ) {
return id;
}
public void setId ( Integer id) {
this . id = id;
}
public String getType ( ) {
return type;
}
public void setType ( String type) {
this . type = type;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public String getDescription ( ) {
return description;
}
public void setDescription ( String description) {
this . description = description;
}
}
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException ( Integer code, String message) {
super ( message) ;
this . code = code;
}
public BusinessException ( Integer code, String message, Throwable cause) {
super ( message, cause) ;
this . code = code;
}
public Integer getCode ( ) {
return code;
}
public void setCode ( Integer code) {
this . code = code;
}
}
public class SystemException extends RuntimeException {
private Integer code;
public SystemException ( Integer code, String message) {
super ( message) ;
this . code = code;
}
public SystemException ( Integer code, String message, Throwable cause) {
super ( message, cause) ;
this . code = code;
}
public Integer getCode ( ) {
return code;
}
public void setCode ( Integer code) {
this . code = code;
}
}
public interface BookService {
public boolean save ( Book book) ;
public boolean update ( Book book) ;
public boolean delete ( Integer id) ;
public Book getById ( Integer id) ;
public List < Book > getAll ( ) ;
}
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public boolean save ( Book book) {
bookDao. save ( book) ;
return true ;
}
public boolean update ( Book book) {
bookDao. update ( book) ;
return true ;
}
public boolean delete ( Integer id) {
bookDao. delete ( id) ;
return true ;
}
public Book getById ( Integer id) {
return bookDao. getById ( id) ;
}
public List < Book > getAll ( ) {
return bookDao. getAll ( ) ;
}
}
# jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db
jdbc.username=root
jdbc.password=root
@RunWith ( SpringJUnit4ClassRunner . class )
@ContextConfiguration ( classes = SpringConfig . class )
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById ( ) {
Book book = bookService. getById ( 1 ) ;
System . out. println ( book) ;
}
@Test
public void testGetAll ( ) {
List < Book > all = bookService. getAll ( ) ;
System . out. println ( all) ;
}
}
<?xml version="1.0" encoding="UTF-8"?>
< project xmlns = " http://maven.apache.org/POM/4.0.0" xmlns: xsi= " http://www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation= " http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0.0</ modelVersion>
< groupId> org.example</ groupId>
< artifactId> SSM</ artifactId>
< version> 1.0-SNAPSHOT</ version>
< packaging> war</ packaging>
< dependencies>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-webmvc</ artifactId>
< version> 5.2.10.RELEASE</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-jdbc</ artifactId>
< version> 5.2.10.RELEASE</ version>
</ dependency>
< dependency>
< groupId> org.springframework</ groupId>
< artifactId> spring-test</ artifactId>
< version> 5.2.10.RELEASE</ version>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis</ artifactId>
< version> 3.5.6</ version>
</ dependency>
< dependency>
< groupId> org.mybatis</ groupId>
< artifactId> mybatis-spring</ artifactId>
< version> 1.3.0</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
< version> 5.1.47</ version>
</ dependency>
< dependency>
< groupId> com.alibaba</ groupId>
< artifactId> druid</ artifactId>
< version> 1.1.16</ version>
</ dependency>
< dependency>
< groupId> junit</ groupId>
< artifactId> junit</ artifactId>
< version> 4.12</ version>
< scope> test</ scope>
</ dependency>
< dependency>
< groupId> javax.servlet</ groupId>
< artifactId> javax.servlet-api</ artifactId>
< version> 3.1.0</ version>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> com.fasterxml.jackson.core</ groupId>
< artifactId> jackson-databind</ artifactId>
< version> 2.9.0</ version>
</ dependency>
</ dependencies>
< build>
< plugins>
< plugin>
< groupId> org.apache.tomcat.maven</ groupId>
< artifactId> tomcat7-maven-plugin</ artifactId>
< version> 2.1</ version>
< configuration>
< port> 80</ port>
< path> /</ path>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>