1, What is spring MVC
1. Concept: Spring MVC is a convenient web framework provided by spring. It is composed of processor mapping, processor (controller), dispatcher servlet, view parser and view.
2. Operation view:
1. The user sends a request to the front-end controller DispatcherServlet
2. The dispatcher servlet receives a request to call the handler mapping processor mapper.
3. The processor mapper finds the specific processor according to the request url, generates the processor object Handler and the processor interceptor (if any) and returns it to the dispatcher servlet.
4. The dispatcher servlet invokes the processor through the Handler adapter (which makes the Handler implementation more flexible)
5. Execution processor (Controller, also known as back-end Controller).
6. The Controller returns to ModelAndView after execution (a bridge connecting the business logic layer and the presentation layer, holding a ModelMap object and a View object).
7. The HandlerAdapter returns the controller execution result ModelAndView to the dispatcher servlet
8. DispatcherServlet passes ModelAndView to viewrestrover view parser
9. The viewrestrover returns a specific View after parsing
10. The dispatcher servlet renders the View (populates the View with ModelMap model data).
11. Dispatcher servlet response user
2, Spring MVC configuration
1.pom dependency
<!--add to Tomcat rely on--> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> </plugins> </build>
<!--springmvc rely on--> <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>
<!--json rely on--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> </dependencies>
Project structure. The code here demonstrates the key points of the Controller layer
2.spring configuration
(1) Spring MVC configuration class
@Configuration //Scan controller package and spring MVC support @ComponentScan({"com.dengzhihong.controller","com.dengzhihong.config"}) //Turn on json data conversion @EnableWebMvc public class SpringMVC_Config { }
(2) Spring configuration class
@Configuration //There are two ways to set scanning except Controller package //@ComponentScan({"com.dengzhihong.dao","com.dengzhihong.pojo","com.dengzhihong.service"}) @ComponentScan(value = "com.dengzhihong", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)) public class Spring_config { }
(3) Spring MVC container configuration class
public class ServletContainnerInit_Config extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{Spring_config.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMVC_Config.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } /** * Solve post garbled code * @return */ @Override protected Filter[] getServletFilters() { CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("utf-8"); return new Filter[]{filter}; }
Spring MVC container can also be implemented by inheriting AbstractDispatcherServletInitializer, but it is troublesome and is not recommended.
demonstration:
public class ServletContainnerInit_Config extends AbstractDispatcherServletInitializer{ /* * * //Load the spring MVC configuration class to produce the spring MVC container * @return */ @Override protected WebApplicationContext createServletApplicationContext() { //Initialize WebApplication object AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); //Load the specified configuration class ctx.register(SpringMVC_Config.class); return ctx; } /** * Set the request mapping path processed by the spring MVC controller * @return */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } /** * Load spring configuration class * @return */ @Override protected WebApplicationContext createRootApplicationContext() { //Initializing Spring container objects AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); //Load the specified configuration class ctx.register(Spring_config.class); return ctx; } }
(4) Mapping classes to static resources
@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { /** * Set the static resource access filter. The current class needs to be set as the configuration class and scanned and loaded */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { //When accessing / pages /???? When, find the contents from the / pages directory registry.addResourceHandler("/pages/**") .addResourceLocations("/pages/"); registry.addResourceHandler("/js/**") .addResourceLocations("/js/"); registry.addResourceHandler("/css/**") .addResourceLocations("/css/"); registry.addResourceHandler("/plugins/**") .addResourceLocations("/plugins/"); } }
If the spring MVC configuration class implements the WebMvcConfigurer interface, the above static resource mapping class may not be used
@Configuration @ComponentScan({"com.dengzhihong.controller"}) @EnableWebMvc /** * Implementing the WebMvcConfigurer interface can simplify development, but it is invasive */ public class SpringMvc_Config implements WebMvcConfigurer { @Autowired private ProjectInterception projectInterception; @Autowired private ProjectInterception2 projectInterception2; /** * Set the static resource access filter. The current class needs to be set as the configuration class and scanned and loaded */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //When accessing / pages /???? When, find the contents from the / pages directory registry.addResourceHandler("/pages/**") .addResourceLocations("/pages/"); registry.addResourceHandler("/js/**") .addResourceLocations("/js/"); registry.addResourceHandler("/css/**") .addResourceLocations("/css/"); registry.addResourceHandler("/plugins/**") .addResourceLocations("/plugins/"); } /** * Register mvc request interceptor */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterception).addPathPatterns("/books","/books/*"); registry.addInterceptor(projectInterception2).addPathPatterns("/books","/books/*"); } }
Two interceptors are registered under the spring MVC configuration class
Interceptor specific code
/** * SpringMVC Interceptor: * - effect: * 1. Executes pre-set code before and after the specified method call * 2. Block the execution of the original method * 3. Summary: enhancements * -Core principle: AOP idea */ //Managed by spring MVC container @Component public class ProjectInterception implements HandlerInterceptor { /** *What was executed before the original method call *The return value type can intercept the execution of control. true releases and false terminates * handler:The called processor object is essentially a Method object, which repackages the Method object in reflection technology */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("----------preHandle1"); return true; } /** * Content executed after the original method call: * Note: if the processor method has an exception, the method will not execute */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("----------postHandle1"); } /** *Contents executed after the original method call is completed: * Note: the method executes regardless of whether there is an exception inside the processor method. */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("----------afterCompletion1"); } }
3, Request response (key)
1.controller layer mode I
@Controller //Set request mapping prefix @RequestMapping("user") public class RequestMapping_ { //Set the mapping path URL, and requestparam receives the form or path data @RequestMapping("/hello") //Set response body @ResponseBody public String hello(@RequestParam("name")String name, int age){ System.out.println(name+":"+age); return "hello"; } /** * Pass entity parameter user */ @RequestMapping("/user") @ResponseBody public String user(User user){ System.out.println(user); return "user"; } /** * Nested POJO parameters: parameters can be transferred by setting the name of nested attributes according to the hierarchy */ @RequestMapping("/pojoContain") @ResponseBody public String classs(Classs classs){ System.out.println(classs); return "classs"; } /** * Array parameters */ @RequestMapping("/array") @ResponseBody public String array(String[] likes){ System.out.println(Arrays.toString(likes)); return "array"; } /** * Set parameters: request parameters with the same name can be mapped to the set object with the corresponding name as data using the @ RequestParam annotation */ @RequestMapping("/list") @ResponseBody public String list(@RequestParam List<String> likes){ System.out.println(likes); return "list"; } /** * Set parameter json format: * Use the @ RequestBody annotation to map the externally passed json array data to the collection object of the formal parameter as data. * Function: pass the data contained in the request body to the request parameters. This annotation can only be used once by a processor method */ @RequestMapping("/listJson") @ResponseBody public String listJson(@RequestBody List<String> likes){ System.out.println(likes); return "listJson"; } /** * json The user: json data of the passed entity parameter is the same as the attribute name of the formal parameter object. You can receive parameters by defining POJO type formal parameters */ @RequestMapping("/userJson") @ResponseBody public String userJson(@RequestBody User user){ System.out.println(user); return "userJson"; } /** * json Entity collection parameters: the json array data is the same as the collection generic attribute name. You can receive parameters by defining a List type parameter */ @RequestMapping("/listUserJson") @ResponseBody public String listUserJson(@RequestBody List<User> users){ System.out.println(users); return "usersJson"; } /** * Time type parameter: use @ DateTimeFormat annotation to set date type data format. The default format is yyyy/MM/dd. * Internally dependent Converter interface */ @RequestMapping("/date") @ResponseBody public String date(Date date, @DateTimeFormat(pattern = "yyyy-MM-dd") Date date1, @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date2 ){ System.out.println(date); System.out.println(date1); System.out.println(date2); return "date"; } }
2. Response
@Controller public class Response_ { /** * Page Jump */ @RequestMapping("/page") public String index() throws IOException { return "page.jsp"; } /** * Response POJO object * The return value is the entity class object. Setting the return value as the entity class type can return the json data of the corresponding object, * You need to rely on the @ ResponseBody annotation and the @ EnableWebMvc annotation. */ @RequestMapping("/toJsonPOJO") @ResponseBody public User toJsonPOJO(){ System.out.println("return json Object data"); User user = new User(); user.setName("itcast"); user.setAge(15); return user; } /** * Response POJO collection object: * //The return value is a collection object. Set the return value as a collection type to return the json array data of the corresponding collection. */ @RequestMapping("/toJsonList") @ResponseBody public List<User> toJsonList(){ System.out.println("return json Aggregate data"); User user1 = new User(); user1.setName("Intelligence Podcast"); user1.setAge(15); User user2 = new User(); user2.setName("Dark horse programmer"); user2.setAge(12); List<User> userList = new ArrayList<User>(); userList.add(user1); userList.add(user2); return userList; } }
3. The most important Restful style
/*@Controller //It means that all methods have @ ResponseBody @ResponseBody*/ //Represents the above two @RestController @RequestMapping("/users") public class REST { // @RequestMapping(method = RequestMethod.GET) @GetMapping public String get(){ System.out.println("get"); return "get"; } // @RequestMapping(method = RequestMethod.POST) @PostMapping public String post(@RequestBody User user){ System.out.println(user); return "post"; } /** * Path parameters */ // @RequestMapping(value = "/{id}",method = RequestMethod.DELETE) @DeleteMapping("/{id}") public String delete(@PathVariable Integer id){ System.out.println("delete:"+id); return "delete"; } // @RequestMapping(method = RequestMethod.PUT) @PutMapping("/{id}") public String put(@RequestBody User user,@PathVariable int id){ System.out.println(id); System.out.println("put:"+user); return "put"; } }
The mapping paths are distinguished by different request modes.
4, Global exception handler
You can set the exception handling method here
/** * @RestControllerAdvice Used to identify the exception handler corresponding to the REST style of the current class. * Note: this annotation has its own @ ResponseBody annotation and @ Component annotation, with corresponding functions */ @RestControllerAdvice public class ProjectExceptionAdvice { /** * System exception * Function: set the handling scheme of the specified exception. The function is equivalent to the controller method. In case of exception, terminate the execution of the original controller and transfer to the current method for execution. * Note: this kind of method can make multiple methods to handle corresponding exceptions according to different exceptions. */ @ExceptionHandler(SystemException.class) public Result doSystemException(SystemException ex){ //Log //Send message to O & M //Send mail to developers, ex objects to developers return new Result(ex.getCode(),null,ex.getMessage()); } /** * Business exception */ @ExceptionHandler(BusinessException.class) public Result doBusinessException(BusinessException ex){ return new Result(ex.getCode(),null,ex.getMessage()); } /** *In addition to custom exception handlers */ @ExceptionHandler(Exception.class) public Result doOtherException(Exception ex){ //Log //Send message to O & M //Send mail to developers, ex objects to developers return new Result(Code.SYSTEM_UNKNOW_ERR,null,"The system is busy, please try again later!"); } }
5, Project complete code demonstration
Because the above is an introduction to spring MVC, the following code will not be used. The project structure is shown in the figure above.
1, pom dependency
<?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>com.itheima</groupId> <artifactId>spring6_SSM</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>11</java.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <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> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <!--section--> <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <!--spring integration mybatis--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.9.RELEASE</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>8080</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
2, jdbc.properties preparation under resources
3, domain entity class, setter and Getter are omitted
public class Book { private Integer id ; private String type ; private String name ; private String description ; }
4, dao layer
public interface BookDao { @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})") public int save(Book book); //The return value represents the number of rows affected @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}") public int update(Book book); @Delete("delete from tbl_book where id = #{id}") public int delete(Integer id); @Select("select * from tbl_book where id = #{id}") public Book getById(Integer id); @Select("select * from tbl_book") public List<Book> getAll(); }
5, config configuration layer
(1)Jdbc_Config configuration class
public class Jdbc_Config { @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 dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource); return dataSourceTransactionManager; } }
6, Mybatis_Config
public class Mybatis_Config { @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setTypeAliasesPackage("com.dengzhihong.domain"); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.dengzhihong.dao"); return mapperScannerConfigurer; } }
7, Spring MVC container configuration class
public class ServletContainnerInit extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{Spring_Config.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvc_Config.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("utf-8"); return new Filter[]{characterEncodingFilter}; } }
8, spring container configuration class
@Configuration @ComponentScan({"com.dengzhihong.service"}) @PropertySource("classpath:jdbc.properties") @Import({Jdbc_Config.class,Mybatis_Config.class}) @EnableTransactionManagement public class Spring_Config { }
9, springMVC configuration class
@Configuration @ComponentScan({"com.dengzhihong.controller"}) @EnableWebMvc /** * Implementing the WebMvcConfigurer interface can simplify development, but it is invasive */ public class SpringMvc_Config implements WebMvcConfigurer { @Autowired private ProjectInterception projectInterception; @Autowired private ProjectInterception2 projectInterception2; /** * Set the static resource access filter. The current class needs to be set as the configuration class and scanned and loaded */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //When accessing / pages /???? When, find the contents from the / pages directory registry.addResourceHandler("/pages/**") .addResourceLocations("/pages/"); registry.addResourceHandler("/js/**") .addResourceLocations("/js/"); registry.addResourceHandler("/css/**") .addResourceLocations("/css/"); registry.addResourceHandler("/plugins/**") .addResourceLocations("/plugins/"); } /** * Register mvc request interceptor */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterception).addPathPatterns("/books","/books/*"); registry.addInterceptor(projectInterception2).addPathPatterns("/books","/books/*"); } }
10, Code class under controller layer
Used to set different response status codes
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; public static final Integer SYSTEM_ERR = 50001; public static final Integer SYSTEM_TIMEOUT_ERR = 50002; public static final Integer SYSTEM_UNKNOW_ERR = 59999; public static final Integer BUSINESS_ERR = 60002; }
11, Result class under controller layer
Used to encapsulate response code and response data, setter and Getter are omitted
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; } }
12, ProjectExceptionAdvice class under controller layer
The global exception handler handles different exceptions
/** * @RestControllerAdvice Used to identify the exception handler corresponding to the REST style of the current class. * Note: this annotation has its own @ ResponseBody annotation and @ Component annotation, with corresponding functions */ @RestControllerAdvice public class ProjectExceptionAdvice { /** * System exception * Function: set the handling scheme of the specified exception. The function is equivalent to the controller method. In case of exception, terminate the execution of the original controller and transfer to the current method for execution. * Note: this kind of method can make multiple methods to handle corresponding exceptions according to different exceptions. */ @ExceptionHandler(SystemException.class) public Result doSystemException(SystemException ex){ //Log //Send message to O & M //Send mail to developers, ex objects to developers return new Result(ex.getCode(),null,ex.getMessage()); } /** * Business exception */ @ExceptionHandler(BusinessException.class) public Result doBusinessException(BusinessException ex){ return new Result(ex.getCode(),null,ex.getMessage()); } /** *In addition to custom exception handlers */ @ExceptionHandler(Exception.class) public Result doOtherException(Exception ex){ //Log //Send message to O & M //Send mail to developers, ex objects to developers return new Result(Code.SYSTEM_UNKNOW_ERR,null,"The system is busy, please try again later!"); } }
13, controller layer
@RestController @RequestMapping("/books") public class BookController { @Autowired @Qualifier("bookService") private BookService bookService; @PostMapping public Result save(@RequestBody Book book) { boolean flag = bookService.save(book); if (flag){ return new Result(Code.SAVE_OK,null); }else { return new Result(Code.SAVE_ERR,null); } } @PutMapping public Result update(@RequestBody Book book) { boolean flag = bookService.update(book); if (flag){ return new Result(Code.UPDATE_OK,null); }else { return new Result(Code.UPDATE_ERR,null); } } @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { boolean falg = bookService.delete(id); if (falg){ return new Result(Code.DELETE_OK,null); }else { return new Result(Code.DELETE_ERR,null); } } @GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Book book = bookService.getById(id); if (book!=null){ return new Result(Code.GET_OK,book); }else { return new Result(Code.GET_ERR,book); } } @GetMapping public Result getAll() { List<Book> bookList = bookService.getAll(); if (bookList.size()>0){ return new Result(Code.GET_OK,bookList); }else { return new Result(Code.GET_ERR,null); } } }
end.