目录

  • SpringMVC入门案例
    • SpringMVC执行流程
    • controller控制器
    • 请求映射路径
    • 参数传递
      • POST请求中文乱码处理
      • @RequestParam 获取URL参数
      • @EnableWebMvc
      • 参数传递(Json)
      • @RequestBody
      • 参数传递(日期类型)
    • 请求与响应
    • REST风格
      • 接收参数的三种方式
      • RESTful快速开发
      • 静态资源访问放行
    • SSM整合
      • 整合配置
      • 功能模块开发
        • 接口测试
      • 表现层数据封装
      • 异常处理
      • 拦截器

使用SpringMVC技术开发web程序流程
1.创建web工程 (Maven结构)
2.设置tomcat服务器,加载web工程(tomcat插件)
3.导入坐标(SpringMVC+Servlet)
4.定义处理请求的功能类(UserController)
5.设置请求映射(配置映射关系)
6.将SpringMVC设定加载到Tomcat容器中

SpringMVC入门案例

1.导maven坐标


<packaging>war</packaging><dependencies><!-- ServletAPI --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!-- SpringMVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency></dependencies><!-- TomCat插件 --><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>

2.创建配置类

@Configuration
@ComponentScan("com.YuZai.controller")
public class SpringmvcConfig {}
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {@Overrideprotected WebApplicationContext createServletApplicationContext() {  //SpringMVC对应的容器对象AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();context.register(SpringmvcConfig.class);return context;}@Overrideprotected String[] getServletMappings() {  //请求是由Tomcat处理还是springMVC处理return new String[]{"/"};  //所有请求都归SpringMVC处理}@Overrideprotected WebApplicationContext createRootApplicationContext() {   //spring配置的对应的容器的对象return null;}
}

AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化web3.0容器的抽象类
AbstractDispatcherServletInitializer提供三个接口方法供用户实现

  1. protected WebApplicationContext createServletApplicationContext()创建Servlet容器,加载SpringMVC对应的bean放入WebApplicationContext对象范围。
  2. protected String[] getServletMappings() 设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理。
  3. protected WebApplicationContext createRootApplicationContext() 如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行。
可以使用它的子类简化开发public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
}

3.创建控制器

@Controller
public class UserController {@RequestMapping("/save")@ResponseBody //将Java对象转换为json格式返回public String save(){System.out.println("save() Running....");return "{鱼仔,18,睡觉}";}}

SpringMVC执行流程

《启动服务器初始化过程》
1. 初始化web容器
2. 执行getServletConfigClasses()方法,创建WebApplicationContext对象
3. 加载SpringMVC配置文件
4. 加载Spring容器中的Bean
5. 加载Controller
6. 执行getServletMappings()方法,所有请求都将通过SpringMVC《单次请求过程》
1.  发送请求 http://localhost/book
2.  web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
3.  解析请求路径 /book
4.  由 /book配置执行对应的方法 selectAll()
5.  执行selectAll()
6.  检测到有@ResponseBody直接将selectAll()方法的返回值作为响应体返回给请求方

controller控制器

请求映射路径

@RequestMapping

参数传递

GET方式传参

请求路径: http://localhost:80/user/save?name=FangYiZe&pw=666999Controller控制层代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/save")@ResponseBody //将Java对象转换为json格式返回public String save(String name, String pw){System.out.println("save() Running......");System.out.println("name"+"=>>>"+name);System.out.println("pw"+"=>>>"+pw);return "{鱼仔,18,睡觉}";}
}运行结果:
save() Running......
name=>>>FangYiZe
pw=>>>666999

POST方式传参

请求路径: http://localhost:80/user/add
PostMan  x-www-form-urlencoded Body数据KEY         VALUE    username    FangYiZe password    666999sex      manController控制层代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(value = "/add",method = RequestMethod.POST)@ResponseBodypublic String add( String username,String password,String sex){System.out.println("add() Running......");System.out.println("username"+"=>>>"+username);System.out.println("password"+"=>>>"+password);System.out.println("sex"+"=>>>"+sex);return "add() Running...";}
}运行结果:
add() Running......
username=>>>FangYiZe
password=>>>666999
sex=>>>man

POST请求中文乱码处理

POST请求中文乱码处理
为web容器添加过滤器并指定字符集public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {//乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}

@RequestParam 获取URL参数

传实体类参数请求URL: http://localhost:80/user/test?age=18&username=喜羊羊&hobby=提出方法&book.bookName=喜羊羊的一生&book.price=99.87controller控制层代码:
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@RequestMapping(value = "/test",method = RequestMethod.GET)public void test( User user){System.out.println("test() Running...");System.out.println("user=>>>>>"+user);}
}
传List集合参数
例: POST请求
请求URL: http://localhost:80/user/test02
请求体: KEY            VALUElikes          a666likes           b666likes           c666controller控制层代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(value = "/test02",method = RequestMethod.POST)public void test02(@RequestParam("likes") List<String> listStr){System.out.println("test02() Running...");System.out.println("listStr=>>>>>"+listStr);}
}运行结果:
test02() Running...
listStr=>>>>>[a666, b666, c666]
[WARNING] No mapping for POST /user/user/test02

@EnableWebMvc

作用: 开启SpringMVC多项辅助功能。
@EnableWebMvc功能之一: 根据类型匹配对应的类型转换器。

参数传递(Json)

导JSON坐标:<!-- JSON --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.3</version></dependency>开启@EnableWebMvc注解
@Configuration
@ComponentScan("com.YuZai.controller")
@EnableWebMvc
public class SpringmvcConfig {}Controller控制层代码:
@Controller
@RequestMapping("/user")
public class UserController {//参数传递(JSON)@RequestMapping("/test03")public void test03(@RequestBody List<String> listStr){System.out.println("test03() Running...");System.out.println("listStr=>>>>>"+listStr);}
}请求URL: http://localhost:80/user/test03
请求体List JSON格式:  ["aaa","bbb","ccc"]运行结果:
test03() Running...
listStr=>>>>>[aaa, bbb, ccc]

POJO实体类的JSON数据请求URL: http://localhost:80/user/test04请求体:  嵌套POJO JSON格式{"username" : "Jack" ,"age" : 19,"hobby" : "唱,跳,rap,篮球","book" :{"bookName" : "投篮的技巧","price" : 100.89}
}Controller控制层代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/test04")public void test04(@RequestBody User user){System.out.println("test04() Running...");System.out.println("user=>>>>>"+user);}
}运行结果
test04() Running...
user=>>>>>User{username='Jack', age=19, hobby='唱,跳,rap,篮球', book=Book{bookName='投篮的技巧', price=100.89}}
List<POJO> JSON格式请求URL: http://localhost:80/user/test05请求体: [{"username":"迪迦超人","age":19,"hobby":"拯救人类","book":{"bookName":"迪迦在地球的一百万年","price":99.99}},{"username":"青蛙王子","age":16}]Controller层代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/test05")public void test05(@RequestBody List<User> listObj){System.out.println("test05() Running...");System.out.println("listObj=>>>>>"+listObj);}
}运行结果:
test05() Running...
listObj=>>>>>[User{username='迪迦超人', age=19, hobby='拯救人类', book=Book{bookName='迪迦在地球的一百万年', price=99.99}}, User{username='青蛙王子', age=16, hobby='null', book=null}]

@RequestBody

参数传递(日期类型)

@DateTimeFormat 指定日期格式请求URL: http://localhost:80/user/test06?date1=2022/02/02&date2=2022-01-01&date3=2022/03/14 11:35:59Controller控制成代码:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/test06")public void test06(Date date1, @DateTimeFormat(pattern = "yyyy-MM-dd") Date date2 , @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date3 ){System.out.println("test06() Running..." );System.out.println( "Data1=>>"+ date1 );System.out.println( "Data2=>>"+ date2 );System.out.println( "Data3=>>"+ date3 );}
}运行结果:
test06() Running...
Data1=>>Wed Feb 02 00:00:00 CST 2022
Data2=>>Sat Jan 01 00:00:00 CST 2022
Data3=>>Mon Mar 14 11:35:59 CST 2022

请求与响应

 响应页面响应数据文本数据json数据
响应页面、跳转页面  (直接返回页面名称)@RequestMapping(value = "/test001",method = RequestMethod.GET)public String test001(){System.out.println("test001() Running...");return "index.jsp";}报错:[WARNING] No mapping for GET /pages/books.html原因: 被SpringMVC拦截了所有请求
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected String[] getServletMappings() {return new String[]{"/"};  //这就是问题点}
}解决方法: 不走SpringMVC走TomCat  (设置对静态资源的访问放行)
@Configuration
public class SpringmvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) { //作用:添加资源的过滤//当访问 /pages/资源名 时,不通过springMVC,直接访问 /pages/ 下的资源。registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");//同理registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}
响应纯文本数据  @Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(value = "/test002",method = RequestMethod.GET)@ResponseBodypublic String test002(){System.out.println("test002() Running...");return "response text";}}
响应POJO对象
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/test003")@ResponseBodypublic User test003(){User user = new User();user.setUsername("小小怪");user.setHobby("挨揍");return user;}}
响应POJO集合@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/test004")@ResponseBodypublic List<User> test004(){User user1 = new User();User user2 = new User();user1.setUsername("翼龙");user2.setUsername("霸王龙");ArrayList<User> users = new ArrayList<>();users.add(user1);users.add(user2);return users;}
}

REST风格

REST(Representational State Transfer) 表现形式状态转换传统风格资源描述形式http://localhost/user/getById?id=1http://locahlost/user/saveUserREST风格描述形式http://localhost/user/1http://localhost/user
优点:隐藏资源的访问路径,无法通过地址得知对资源是可何种操作简化书写按照REST风格访问资源时使用行为动作区分对资源进行了何种操作http://localhost/users   查询全部用户信息 GET (查询)
http://lcoalhost/users/1 查询指定用户信息 GET (查询)
http://localhost/users   添加用户信息 POST (新增/保存)
http://localhost/users   修改用户信息 PUT (修改/更新)
http://localhost/users/1 删除用户信息 DELETE (删除)上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范。
描述模块的名称通常是用复数,也就加s的格式描述,表示此类资源,而非单个资源,例如: users、books...根据REST风格对资源进行访问称为RESTful。
REST 案例案例 GET带参
URL: http://localhost:80/user/9999
Controller:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(value = "/{id}", method = RequestMethod.GET)public void testA(@PathVariable int id){System.out.println("testA Running... ");System.out.println("id =>>> " +id );}
}
运行结果:testA Running... id =>>> 9999-----------------------------------------------------------------
案例 POST请求 带请求体 ({"username":"大鲨鱼","age":998,"hobby":"大吃特吃" })
URL: http://localhost:80/user
Controller:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(method = RequestMethod.POST)public void testC(@RequestBody User user){System.out.println("执行添加操作,增加" +user);}
}
运行结果:执行添加操作,增加User{username='大鲨鱼', age=998, hobby='大吃特吃', book=null}-----------------------------------------------------------------案例 PUT请求 带请求体 ({"username":"大大怪","age":112,"hobby":"敢作敢当" })
URL: http://localhost:80/user
Controller:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(method = RequestMethod.PUT)public void testE(@RequestBody User user){System.out.println("执行修改操作,修改"+user);}
}
运行结果:执行修改操作,修改User{username='大大怪', age=112, hobby='敢作敢当', book=null}

接收参数的三种方式

至此,接收参数的方式一共有三种,分别是: @RequestBody、@RequestParam、@PathVariable,第一种是接收请求体参数,第二种是接收URL传参例: http://localhost:80/user/test?age=18&username=喜羊羊 , 第三种是接收路径参数例: http://localhost:80/user/1

RESTful快速开发

@RestController
@RequestMapping("/user002")
public class User002Controller {@GetMapping("/{id}")    //测试URL:http://localhost:80/user002/1public User selectById(@PathVariable int id ){User user = new User();user.setUsername("暴龙");return user;}@PostMapping   //测试URL:http://localhost:80/user002  请求体: {"username":"暴龙战士","hobby":"炫饭"}public void addUser(@RequestBody User user){System.out.println( "添加新成员=>>>"+user );}@DeleteMapping  //测试URL:http://localhost:80/user002?id=9public void deleteUser(@RequestParam int id){System.out.println("删除成员=>>>"+id);}@PutMapping("/{id}") //测试URL:http://localhost:80/user002/6public void updateUser(@RequestBody User user,@PathVariable int id){System.out.println( "修改id为"+id+"的成员=>>>"+user );}}

静态资源访问放行

记得将此配置类加载到SpringMVC容器中@Configuration
public class SpringmvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) { //作用:添加资源的过滤//当访问 /pages/资源名 时,不通过springMVC,直接访问 /pages/ 下的资源。registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");//同理registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");}
}

SSM整合

SSM整合流程1.创建工程2.SSM整合SpringSpringConfigMyBatisMybatisConfigJdbcConfigjdbc.propertiesSpringMVCServletConfigSpringMvcConfig
3.功能模块表与实体类dao(接口+自动代理)service(接口+实现类)业务层接口测试(整合JUnit)controller表现层接口测试(PostMan)

整合配置

<packaging>war</packaging><!-- SpringMVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.10.RELEASE</version></dependency><!-- Spring整合jdbc --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.10.RELEASE</version></dependency><!-- Spring整合Test --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.10.RELEASE</version></dependency><!-- MyBatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><!-- MyBatis-Spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!-- MySql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version></dependency><!-- junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- ServletAPI --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!-- JSON --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency></dependencies><!-- TomCat插件 --><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>

// 此类是Spring配置类。@Configuration
@ComponentScan({"com.YuZai.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
@EnableTransactionManagement //开启事务
public class SpringConfig {}
resources/jdbc.propertiesjdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/SpringMVCSSM_db
jdbc.username=root
jdbc.password=0000000
com/YuZai/config/JdbcConfig.javapublic 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  //将返回值加载到Spring的IOC容器public DataSource dataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}//事务管理器@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager ds = new DataSourceTransactionManager();ds.setDataSource(dataSource);return ds;}
}
//Spring整合MyBatispublic class MyBatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){  //dataSource由Spring自动装配SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setTypeAliasesPackage("com.YuZai.domain");return factoryBean;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer msc = new MapperScannerConfigurer();msc.setBasePackage("com.YuZai.dao");return msc;}}
com/YuZai/config/ServletConfig.javapublic class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}//乱码处理@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();filter.setEncoding("UTF-8");return new Filter[]{filter};}
}
com/YuZai/config/SpringMvcConfig.java@Configuration
@ComponentScan("com.YuZai.controller")
@EnableWebMvc
public class SpringMvcConfig {}

功能模块开发

domainpublic class Book {private Integer id ;private String type;private String bookName;private String description;构造器方法...getter,setter方法....toString....
}
dao// 增删改查public interface BookDao {//利用mybatis的自动代理写实现@Select("SELECT * FROM tab_book WHERE id=#{id}")  // #{方法的形参名}public Book selectById(Integer id);@Select("SELECT * FROM tab_book ")public List<Book> selectAll();@Insert("INSERT tab_book( TYPE,book_name,description ) VALUES ( #{type},#{bookName},#{description} ); ")  //#{POJO的属性}public void addBook(Book book);@Update("UPDATE tab_book SET TYPE=#{type},book_name=#{bookName},description=#{description} WHERE id=#{id} ; ")  //#{POJO的属性}public void updateBook(Book book);@Delete("DELETE FROM tab_book WHERE id=#{id} ;")  //#{方法的形参名}public void deleteBook(Integer id);}
service // 业务层接口@Transactional
public interface BookService {public Book selectById(Integer id);public List<Book> selectAll();public boolean addBook(Book book);public boolean updateBook(Book book);public boolean deleteBook(Integer id);
}
service.impl@Service
public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;@Overridepublic Book selectById(Integer id) {Book book = bookDao.selectById(id);return book;}@Overridepublic List<Book> selectAll() {List<Book> books = bookDao.selectAll();return books;}@Overridepublic boolean addBook(Book book) {bookDao.addBook(book);return true;}@Overridepublic boolean updateBook(Book book) {bookDao.updateBook(book);return true;}@Overridepublic boolean deleteBook(Integer id) {bookDao.deleteBook(id);return true;}
}
controllerpackage com.YuZai.controller;@RestController
@RequestMapping("/books")
public class BookController {@Autowiredprivate BookServiceImpl bookService;@GetMappingpublic List<Book> selectAll(){   // 测试URL: http://localhost:80/booksList<Book> books = bookService.selectAll();return books;}@GetMapping("/{id}")public Book selectById(@PathVariable Integer id){Book book = bookService.selectById(id);return book;}@PostMapping    // 测试URL: http://localhost:80/books  post 请求体:{"type":"动漫类","bookName":"迪迦爱学习","description":"超励志"}public boolean addBook(@RequestBody Book book){boolean b = bookService.addBook(book);return b;}@PutMapping    // 测试URL:http://localhost:80/books  Put 请求体:{"type":"动漫类","bookName":"打大怪将军","description":"超腻害","id":"4"}public boolean updateBook(@RequestBody Book book){boolean b = bookService.updateBook(book);System.out.println(book);return b;}@DeleteMapping("/{id}")      //测试URL:http://localhost:80/books/5 DELETEpublic boolean deleteBook(@PathVariable Integer id){boolean b = bookService.deleteBook(id);return b;}}
接口测试

//Spring整合Junit@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {@Autowiredprivate BookServiceImpl bookService;@Testpublic void TestSelectById(){Book book = bookService.selectById(1);System.out.println(book);}@Testpublic void TestSelectAll(){List<Book> books = bookService.selectAll();System.out.println(books);}}

表现层数据封装

后端统一数据模型传给前端的。设置统一数据返回结果类:
public class Result{private Object data;   //封装数据private Integer code;  //状态码private String message; //消息}
需要注意的是: 这就是前后端通讯的协议,没有固定格式,Result类中的字段并不固定,根据需要增减,提供构造方法。

public class Code {public static final Integer SELECT_OK = 20011;public static final Integer ADD_OK = 20021;public static final Integer DELETE_OK = 20031;public static final Integer UPDATE_OK = 20041;public static final Integer SELECT_ERR = 20010;public static final Integer ADD_ERR = 20020;public static final Integer DELETE_ERR= 20030;public static final Integer UPDATE_ERR = 20040;}//表现层
@RestController
@RequestMapping("/books")
public class BookController {@Autowiredprivate BookServiceImpl bookService;@GetMappingpublic Result selectAll(){   // 测试URL: http://localhost:80/books GETList<Book> books = bookService.selectAll();System.out.println(books);Integer code = books.size() != 0 ? Code.SELECT_OK : Code.SELECT_ERR;String msg = books.size() != 0 ? "" : "查询数据失败,请重试!";return new Result(books,code,msg);}@GetMapping("/{id}")public Result selectById(@PathVariable Integer id){   // 测试URL: http://localhost:80/books/1   GETBook book = bookService.selectById(id);Integer code = book != null ? Code.SELECT_OK : Code.SELECT_ERR;String msg = book != null ? "" : "查询数据失败,请重试!";return new Result(book,code,msg);}@PostMapping    // 测试URL: http://localhost:80/books  post 请求体:{"type":"动漫类","bookName":"迪迦爱学习","description":"超励志"}public Result addBook(@RequestBody Book book){boolean b = bookService.addBook(book);return new Result(b,b?Code.ADD_OK:Code.ADD_ERR);}
}

异常处理

程序开发中不可避免会遇到异常。 程序正常运行时理应返回统一格式的Result封装数据。但若是出现异常返回给前端的就是一堆html代码。异常得分类处理:出现异常现象的常见位置与常见诱因如下:框架内部抛出的异常 :因使用不合规导致数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)表现层抛出的异常: 因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)工具类拋出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)解决思想:数据层、业务层、表现层均出现异常,异常处理代码书写在哪一层? 解:全部往上抛,抛到表现层进行处理。表现层每个方法都得进行异常处理,代码书写量巨大,如何解决?解:AOP思想。以上 异常分类处理、统一表现层处理、AOP处理的操作,SpringMVC已经做了封装。----- 异常处理器!
异常处理器集中的、统一的处理项目中出现的异常。package com.YuZai.controller;
//异常处理器
@RestControllerAdvice
public class ProjectExceptionAdvice {@ExceptionHandler(Exception.class)public Result doException(Exception ex){return new Result(null,null,"后台出错了");}}

项目异常分类业务异常(BusinessException)规范的用户行为产生的异常不规范的用户行为操作产生的异常系统异常(SystemException)项目运行过程中可预计且无法避免的异常其他异常(Exception)编程人员未预期到的异常项目异常处理方案业务异常(BusinessException)◆发送对应消息传递给用户, 提醒规范操作系统异常(SystemException)◆发送固定消息传递给用户,安抚用户.◆发送特定消息给运维人员,提醒维护◆记录日志其他异常(Exception)◆发送固定消息传递给用户,安抚用户◆发送特定消息给编程人员,提醒维护(纳入预期范围内)◆记录日志
自定义业务型异常package com.YuZai.exception;public class BusinessException extends RuntimeException{private Integer code;public Integer getCode() {return code;    }public void setCode(Integer code) {  this.code = code;    }public BusinessException(String message, Integer code) {super(message);this.code = code;}public BusinessException(String message, Throwable cause, Integer code) {super(message, cause);this.code = code;}
}
自定义系统型异常package com.YuZai.exception;public class SystemException extends RuntimeException{private Integer code;public Integer getCode() { return code;  }public void setCode(Integer code) { this.code = code;    }public SystemException(String message, Integer code) {super(message);this.code = code;}public SystemException(String message, Throwable cause, Integer code) {super(message, cause);this.code = code;}}
自定义异常编码public class Code {public static final Integer SYSTEM_ERR = 50001;public static final Integer BUSINESS_ERR = 60001;public static final Integer SYSTEM_UNKNOW_ERR = 59999;
}
模拟激活异常package com.YuZai.service.impl;@Service
public class BookServiceImpl implements BookService {@Autowiredprivate BookDao bookDao;@Overridepublic Book selectById(Integer id) {//模拟业务异常  测试URL:http://localhost:80/books/200if(id==200){throw new BusinessException("禁止违规操作!",Code.BUSINESS_ERR);}//模拟未知类异常   测试URL:http://localhost:80/books/300if (id==300){throw new ArithmeticException();}//将可能出现的异常进行包装,转换成自定义异常  测试URL:http://localhost:80/books/1try {System.out.println(2/0);}catch (ArithmeticException e){throw new SystemException("系统繁忙,请稍后重试!",e, Code.SYSTEM_ERR);}Book book = bookDao.selectById(id);return book;}}
异常处理器 拦截并处理异常package com.YuZai.controller;@RestControllerAdvice
public class ProjectExceptionAdvice {/*** 处理系统类异常* @param ex* @return*/@ExceptionHandler(SystemException.class)public Result doSystemException(SystemException ex){//记录日志//通知运维//发邮件给开发,将ex对象发给开发//return信息给前端return new Result(null,ex.getCode(),ex.getMessage());}/*** 业务类异常* @param ex* @return*/@ExceptionHandler(BusinessException.class)public Result doBusinessException(BusinessException ex){//返回信息给前端return new Result(null,ex.getCode(),ex.getMessage());}/*** 其他类异常* @param ex* @return*/@ExceptionHandler(Exception.class)public Result doException(Exception ex){//记录日志//通知运维//发邮件给开发,将ex对象发给开发//return信息给前端return new Result(null,Code.SYSTEM_UNKNOW_ERR,"系统维护,请稍后再试! ");}}
异常处理器效果对比{"data": null,"code": 50001,"message": "系统繁忙,请稍后重试!"
}{"data": {"id": 1,"type": "搞笑类","bookName": "懒羊羊考试","description": "小孩子喜欢看"},"code": 20011,"message": ""
}

拦截器

拦截器是一种动态拦截方法调用的机制作用:在指定的方法调用前后执行预先设定后的代码阻止原始方法的执行拦截器与过滤器区别归属不同:Filter属于Servlet技术,Interceptor属于SprinigMVC技术拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
入门案例: 步骤一// 拦截器  (为SpringMVC服务,得加载到SpringMvc容器中)package com.YuZai.controller.interceptor;@Component
public class ProjectInterceptor implements HandlerInterceptor {@Override  // preHandle()表示拦截原始操作之前运行的代码public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle() Running...");return true;  // 如果返回false,表示终止原始操作的进行,自然的后面的postHandle()、afterCompletion()也不会执行。}@Override // postHandle()表示拦截原始操作之后运行的代码public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle() Running...");}@Override //public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion() Running...");}
}
入门案例:步骤二package com.YuZai.config;@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");  //测试URL:http://localhost/pages/books.html}@Autowiredprivate ProjectInterceptor projectInterceptor;@Overrideprotected void addInterceptors(InterceptorRegistry registry) {//进行具体的拦截器配置registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}}
简化配置类开发小技巧SpringMvcSupport
SpringMvcConfig@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/css/**").addResourceLocations("/css/");registry.addResourceHandler("/js/**").addResourceLocations("/js/");registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");  //测试URL:http://localhost/pages/books.html}@Autowiredprivate ProjectInterceptor projectInterceptor;@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");}
}@Configuration
@ComponentScan({"com.YuZai.controller","com.YuZai.config"})
@EnableWebMvc
public class SpringMvcConfig {}可以变为:  缺点: 入侵性较强,因为实现了接口,此程序就和Spring强绑定了(这个类跟Spring的API关联在一起了)
@Configuration
@ComponentScan({"com.YuZai.controller","com.YuZai.config"})
@EnableWebMvc
public class SpringMvcConfigF implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {}@Overridepublic void addInterceptors(InterceptorRegistry registry) {}
}

拦截器的执行流程:

拦截器参数@Override  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true; }参数:request:请求对象response:响应对象handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装 (可以这么说:拿到了handler对象就可以操作原始执行的那个方法)
返回值: 返回值为false,被拦截的处理器将不执行。public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}
参数:ModelAndView (现在的开发模式已经不使用它了) 如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整。 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
参数:Exception (完全可以通过SpringMVC替换这里进行的操作)如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理。
当配置多个拦截器时,形成拦截器链// 当配置多个拦截器时,形成拦截器链
com/YuZai/controller/interceptor/ProjectInterceptor02.java
@Component
public class ProjectInterceptor02 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle02() Running...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle02() Running...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion02() Running...");}
}com/YuZai/config/SpringMvcSupport.java
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowiredprivate ProjectInterceptor projectInterceptor;@Autowiredprivate ProjectInterceptor02 projectInterceptor02;@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");registry.addInterceptor(projectInterceptor02).addPathPatterns("/books","/books/*");}}

拦截器链的运行顺序preHandle: 与配置顺序相同,必定运行postHandle: 与配置顺序相反,可能不运行afterCompletion:与配置顺序相反,可能不运行例: preHandle() Running...preHandle02() Running...postHandle02() Running...postHandle() Running...afterCompletion02() Running...afterCompletion() Running...

SpringMVC全注解开发相关推荐

  1. SpringMVC全注解环境搭建

    源代码: 链接:https://pan.baidu.com/s/1Lxb-riH–YQNIy3c0i8pFA 提取码:y3aq 文档地址:https://shphuang_aliyun.gitee.i ...

  2. springmvc教程--注解开发基础详解

    springmvc教程系列 springmvc史上最好教程(2) springmvc史上最好教程(1) 一. 注解开发-基础 1.1 需求 使用springmvc+mybatis架构实现商品信息维护. ...

  3. SSM全注解开发的网上商城系统

    SL会员商城 1 需求分析 1.1需求陈述 1.2基于UML的需求分析 1.2.1参与者和参与者之间的关系 1.2.2用例与用例之间的关系.参与者与用例的关系 1.2.3用例图 1.2.4用例说明 1 ...

  4. springmvc学习笔记(10)-springmvc注解开发之商品改动功能

    springmvc学习笔记(10)-springmvc注解开发之商品改动功能 springmvc学习笔记(10)-springmvc注解开发之商品改动功能 标签: springmvc springmv ...

  5. 基于全注解的SpringMVC+Spring4.2+hibernate4.3框架搭建

    概述 从0到1教你搭建spring+springMVC+hibernate整合框架,基于注解. 本教程框架为基于全注解的SpringMVC+Spring4.2+hibernate4.3,开发工具为my ...

  6. 使用注解开发SpringMVC详细配置教程

    目录 1.使用注解开发SpringMVC 1.新建一个普通的maven项目,添加web支持 2.在pom.xml中导入相关依赖 3.配置web.xml 4.编写SpringMVC配置文件 1. 自动扫 ...

  7. SpringMVC学习03之使用注解开发SpringMVC

    复习 Spring MVC的特点: 轻量级,简单易学 高效 , 基于请求响应的MVC框架 与Spring兼容性好,无缝结合 约定优于配置 功能强大:RESTful.数据验证.格式化.本地化.主题等 简 ...

  8. 04springMVC结构,mvc模式,spring-mvc流程,spring-mvc的第一个例子,三种handlerMapping,几种控制器,springmvc基于注解的开发,文件上传,拦截器,s

     1. Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2  spring-mv ...

  9. 关于Spring注解开发教程,打包全送你

    摘要:spring是我们web开发中必不可少的一个框架,基于传统的xml方式配置bean总觉得太过繁琐,从spring2.5之后注解的出现可以大大简化我们的配置. 本文分享自华为云社区<如何高效 ...

最新文章

  1. Python中处理时间 —— time模块
  2. Terracotta tc-config.xml配置说明(这个真的是转的)
  3. 在复杂业务中落地 DDD 的实践方法论
  4. syn flood dos
  5. mysql order by 运算_在MySQL中具有ORDER BY的多个LIKE运算符?
  6. volatile实现原理
  7. java框架mybatis配置文件总结一
  8. vue数组对象双向绑定
  9. mysql 编辑数据库内容_详解mysql数据库增删改操作
  10. android dialog 隐藏状态栏_Flutter-最近搞了个项目-启动页Splash,Navigator.pop无法关闭Dialog...
  11. 农历和阳历日期互转,Python实现
  12. postgresql注入笔记
  13. 【Excel从头开始】-2 快速填充/快速分析
  14. Qt游戏编程——飞机大战
  15. python字符串格式化是什么意思_python字符串格式化什么意思
  16. ISCC2017 Misc write up附件题目文件
  17. html字体根据宽度自动调整,css – 根据div大小调整字体大小
  18. 转载:Think in AngularJS:对比jQuery和AngularJS的不同思维模式(大漠穷秋)
  19. 六款视频剪辑神器,做影视剪辑短视频事半功倍,15天有3000
  20. red hat Linux 配置Samba服务器(超详细:内含桥接模式)

热门文章

  1. HTML5+app开发学习之打包配置文件介绍篇
  2. 《海底捞你学不会》探索管理的本质
  3. 在matlab中拟合值,MATLAB中数值拟合的种种办法
  4. 项目中如何修改element-ui的默认样式
  5. java 1.7 jdk 下载地址
  6. win10系统和安全管理工具服务器,手把手教你分析Win10远程服务器管理工具(RSAT)已发布...
  7. 使用C#实现网站用户登录
  8. SQL语句的优化(常规SQL语句的优化)
  9. iCloud中的照片如何导出到个人电脑中进行储存?
  10. Windows个人电脑的自我防护(包括nmap的扫描端口和cmd的跃点追踪)