目录
Servlet容器中的SpringMVC核心前端控制器DispatcherServlet会拦截所有请求,将拦截的请求与@RequestMapping进行匹配,将请求交给匹配的Controller方法进行处理
初始化Servlet容器(web容器),用web配置类的方式替代web.xml(创建一个类继承AbstractDispatcherServletInitializer并重写方法)
- /**
- * 初始化Servlet容器,即web容器(替代web.xml)
- */
- public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
- /**
- * 加载SpringMVC对应的容器对象
- * SpringMVCIOC容器是SpringIOC的子容器(子容器可以引用父容器,反之则不行)
- */
- @Override
- protected WebApplicationContext createServletApplicationContext() {
- AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
- context.register(SpringConfig.class);
- return context;
- }
-
- /**
- * 哪些请求归SpringMVC处理
- */
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};//表示所有请求都贵SpringMVC处理
- }
-
- /**
- * 加载Spring对应的容器对象
- * 可以将Spring和SpringMVC的容器对象合并成只有SpringMVC容器对象,因此此方法可以返回null即可
- */
- @Override
- protected WebApplicationContext createRootApplicationContext() {
- return null;
- }
- }
简化开发(创建一个类继承AbstractAnnotationConfigDispatcherServletInitializer )
- /**
- * 初始化Servlet容器,即web容器(替代web.xml)
- */
- public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
- /**
- * 加载SpringMVC对应的容器对象
- * SpringMVCIOC容器是SpringIOC的子容器(子容器可以引用父容器,反之则不行)
- */
- @Override
- protected Class>[] getServletConfigClasses() {
- return new Class[]{SpringConfig.class};
- }
-
- /**
- * 被Servlet容器拦截的哪些请求归SpringMVC处理
- */
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};
- }
-
- /**
- * 加载Spring对应的容器对象
- * 可以将Spring和SpringMVC的容器对象合并成只有SpringMVC容器对象,因此此方法可以返回null即可
- */
- @Override
- protected Class>[] getRootConfigClasses() {
- return null;
- }
-
- /**
- * 配置过滤器
- * 编码过滤器(过滤器会优先拦截器执行):解决post乱码问题
- */
- @Override
- protected Filter[] getServletFilters() {
- CharacterEncodingFilter filter = new CharacterEncodingFilter();
- filter.setEncoding("UTF-8");
- filter.setForceEncoding(true);
- return new Filter[]{filter};
- }
-
- /**
- * 配置文件上传解析器
- * 不是用的:org.springframework.web.multipart.commons.CommonsMultipartResolver(额外导包commons-fileupload)
- * 而是用的:org.springframework.web.multipart.support.StandardServletMultipartResolver(SpringMVC自带)
- */
- @Override
- protected void customizeRegistration(ServletRegistration.Dynamic registration) {
- super.customizeRegistration(registration);
- String location = "";
- long maxFileSize = 20971520; //文件大小限制byte(20M)
- long maxRequestSize = 41943040; //请求大小限制byte(40M)
- int fileSizeThreshold = 0; //文件大小阈值
- registration.setMultipartConfig(new MultipartConfigElement(location, maxFileSize, maxRequestSize, fileSizeThreshold));//配置对multipart的支持
- }
- }
| 分类 | 注解 | 说明 |
| @RequestMapping(path="/path",method=RequestMapping.POST) | 映射请求(用在"类/方法"上) @GetMapping=@RequestMapping(method=RequestMapping.GET) @PostMapping @DeleteMapping @PutMapping | |
| 接收 | @RequestHeader("请求头key") | 接收请求头中的参数 |
| @RequestParam("userNmae") String name | 给Controller类方法形参起别名 | |
| @DatetimeFormat(pattern="yyyy-MM-dd HH:mm:ss:SSS") | 可以用在pojo类的属性上,将属性接收的对应格式的字符串转换为Date 也可以用在Controller方法形参前,接收对应格式的字符串转换为Date | |
| @RequestBody User user | 接收POST请求体中的JSON字符串,并封装到JavaBean中 | |
| @PathVariable | RESTful方式,接收"路径变量" | |
| 响应 | @ResponseBody | 将"类/方法"返回的数据转换为JSON对象 |
| @RestController | 用在类上,相当于@Controller+@ResponseBody |
注解选择:
请求参数有多个时,将多个参数写成json格式,后台以json格式接收,@RequestBody使用广泛
请求参数非json时,用@RequestParam接收
请求参数通常只有1个时,可以用@PathVariable接收
- @Controller
- public class TeacherController {
-
- private static final Logger log = LoggerFactory.getLogger(TeacherController.class);
-
- @Autowired
- private TeacherService userService;
-
- @RequestMapping("/save")
- @ResponseBody
- public Teacher save(@RequestBody Teacher teacher) {
- teacher.setName("王五");
- teacher.setAge(44);
- teacher.setPosition("英语老师");
- log.info(String.valueOf(teacher));
- return teacher;
- }
- }
REST(Representational State Transfer)表现层资源状态转换
RESTful按照REST风格访问资源
(1) 传统风格
http://localhost/user/getById?id=1 //查询用户(GET请求)
http://localhost/user/deleteById?id=1 //删除用户(GET请求)
http://localhost/user/addUser //新增用户(POST请求)
http://localhost/user/updateUser //修改用户(POST请求)
(2) REST风格
http://localhost/users/1 //查询用户或删除用户
http://localhost/users //添加用户或修改用户
REST风格通常在的映射地址后加s(此s不是复数形式,而是style的缩写,例如users)
REST风格优点:书写简化,隐藏访问路径(更加安全)
REST风格访问资源是用行为动作进行区分,可以用同一个请求路径,实现不同的功能
http://localhost/users/1 GET方式(查询),DELETE方式(删除)
http://localhost/users POST方式(新增),PUT方式(修改)
前端代码:
- addTeacher() {
- axios.post("/teachers", {
- position: '体育老师',
- name: '赵四',
- age: 54
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(response => {
- alert(response.data)
- })
- },
- updateTeacher() {
- axios.put("/teachers", {
- position: '物理老师',
- name: '龙武',
- age: 77
- }, {
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- }).then(response => {
- alert(response.data)
- })
- },
- deleteTeacher(){
- axios.delete("/teachers/lisa/66", {
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(response => {
- alert(response.data)
- })
- },
- queryTeacher(){
- axios.get("/teachers/gods", {
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(response => {
- alert(response.data)
- })
- },
- queryAllTeacher(){
- axios.get("/teachers", {
- }, {
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(response => {
- alert(response.data)
- })
- }
后台代码:
- @RestController
- @RequestMapping("/teachers")
- public class TeacherController {
-
- @Autowired
- private TeacherService teacherService;
-
- private static final Logger log = LoggerFactory.getLogger(TeacherController.class);
-
- @PostMapping
- public String add(@RequestBody Teacher teacher) {
- log.info("新增teacher信息为:" + teacher);
- return "{'info':'add success'}";
- }
-
- @PutMapping
- public String update(@RequestParam String position, @RequestParam String name, @RequestParam Integer age) {
- Teacher teacher = new Teacher();
- teacher.setPosition(position);
- teacher.setName(name);
- teacher.setAge(age);
- log.info("修改teacher为:" + teacher);
- return "{'info':'update success'}";
- }
-
- /**
- * {name}将"请求路径"倒数第二个作为路径变量
- * {age}将"请求路径"最后一个作为路径变量
- *
- * @PathVariable 接收名为id或age的路径变量
- */
- @DeleteMapping("/{name}/{age}")
- public String delete(@PathVariable String name, @PathVariable Integer age) {
- log.info("删除name为" + name + ",age为" + age + "的teacher");
- return "{'info':'delete success'}";
- }
-
- @GetMapping("/{name}")
- public String query(@PathVariable String name) {
- log.info("查询name为" + name + "的teacher");
- return "{'info':'query success'}";
- }
-
- @GetMapping
- public String queryAll() {
- log.info("查询全部的teacher");
- return "{'info':'query all success'}";
- }
- }
因为所有的请求都会被Servlet容器拦截,而通过web配置类设置的又是将所有拦截的请求交给SpringMVC去处理,导致即使访问一些静态资源(html,css,js,img等)也会被拦截后交给SpringMVC处理,而SpringMVC通过请求路径映射又找不到对应的@RequestMaping,就会报404错误
我们需要的是访问接口交给SpringMVC映射处理,访问静态资源放行,因此需要一个SpringMVESupport配置类继承WebMvcConfigurationSupport类,并重写addResourceHandlers方法
- /**
- * 放行资源访问
- * 此类需要被SpringIOC容器扫描到
- */
- @Configuration //注意此类虽然用@Configuration注解了,但要区别于Spring容器的@Configuration,所以不能在Spring配置类中用@Import引入这个类,也不能Spring配置类自己继承WebMvcConfigurationSupport,而只能单独使用这个类并加上@Configuration
- public class SpringMVCSupportConfig extends WebMvcConfigurationSupport {
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- //被servlet拦截的"请求路径"如果是/html/**,不要被交给MVC处理,而是交给Tomcat处理(将/html/**请求放行,并用html目录下的资源去匹配)
- registry.addResourceHandler("/html/**").addResourceLocations("/html/");
- registry.addResourceHandler("/index.html").addResourceLocations("/index.html");
- }
- }