• SpringMVC


    目录

    1 项目搭建

    1.1 运行原理

    1.2 创建web容器

    1.3 常用注解

    1.4 代码示例

    2 REST风格

    2.1 资源访问对比

    2.2 实现原理

    2.3 示例代码

    3 放行访问


    1 项目搭建

    1.1 运行原理

            Servlet容器中的SpringMVC核心前端控制器DispatcherServlet会拦截所有请求,将拦截的请求与@RequestMapping进行匹配,将请求交给匹配的Controller方法进行处理

    1.2 创建web容器

            初始化Servlet容器(web容器),用web配置类的方式替代web.xml(创建一个类继承AbstractDispatcherServletInitializer并重写方法)

    1. /**
    2. * 初始化Servlet容器,即web容器(替代web.xml)
    3. */
    4. public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    5. /**
    6. * 加载SpringMVC对应的容器对象
    7. * SpringMVCIOC容器是SpringIOC的子容器(子容器可以引用父容器,反之则不行)
    8. */
    9. @Override
    10. protected WebApplicationContext createServletApplicationContext() {
    11. AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    12. context.register(SpringConfig.class);
    13. return context;
    14. }
    15. /**
    16. * 哪些请求归SpringMVC处理
    17. */
    18. @Override
    19. protected String[] getServletMappings() {
    20. return new String[]{"/"};//表示所有请求都贵SpringMVC处理
    21. }
    22. /**
    23. * 加载Spring对应的容器对象
    24. * 可以将Spring和SpringMVC的容器对象合并成只有SpringMVC容器对象,因此此方法可以返回null即可
    25. */
    26. @Override
    27. protected WebApplicationContext createRootApplicationContext() {
    28. return null;
    29. }
    30. }

            简化开发(创建一个类继承AbstractAnnotationConfigDispatcherServletInitializer )

    1. /**
    2. * 初始化Servlet容器,即web容器(替代web.xml)
    3. */
    4. public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    5. /**
    6. * 加载SpringMVC对应的容器对象
    7. * SpringMVCIOC容器是SpringIOC的子容器(子容器可以引用父容器,反之则不行)
    8. */
    9. @Override
    10. protected Class[] getServletConfigClasses() {
    11. return new Class[]{SpringConfig.class};
    12. }
    13. /**
    14. * 被Servlet容器拦截的哪些请求归SpringMVC处理
    15. */
    16. @Override
    17. protected String[] getServletMappings() {
    18. return new String[]{"/"};
    19. }
    20. /**
    21. * 加载Spring对应的容器对象
    22. * 可以将Spring和SpringMVC的容器对象合并成只有SpringMVC容器对象,因此此方法可以返回null即可
    23. */
    24. @Override
    25. protected Class[] getRootConfigClasses() {
    26. return null;
    27. }
    28. /**
    29. * 配置过滤器
    30. * 编码过滤器(过滤器会优先拦截器执行):解决post乱码问题
    31. */
    32. @Override
    33. protected Filter[] getServletFilters() {
    34. CharacterEncodingFilter filter = new CharacterEncodingFilter();
    35. filter.setEncoding("UTF-8");
    36. filter.setForceEncoding(true);
    37. return new Filter[]{filter};
    38. }
    39. /**
    40. * 配置文件上传解析器
    41. * 不是用的:org.springframework.web.multipart.commons.CommonsMultipartResolver(额外导包commons-fileupload)
    42. * 而是用的:org.springframework.web.multipart.support.StandardServletMultipartResolver(SpringMVC自带)
    43. */
    44. @Override
    45. protected void customizeRegistration(ServletRegistration.Dynamic registration) {
    46. super.customizeRegistration(registration);
    47. String location = "";
    48. long maxFileSize = 20971520; //文件大小限制byte(20M)
    49. long maxRequestSize = 41943040; //请求大小限制byte(40M)
    50. int fileSizeThreshold = 0; //文件大小阈值
    51. registration.setMultipartConfig(new MultipartConfigElement(location, maxFileSize, maxRequestSize, fileSizeThreshold));//配置对multipart的支持
    52. }
    53. }

    1.3 常用注解

    分类注解说明
    @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中
    @PathVariableRESTful方式,接收"路径变量"
    响应@ResponseBody将"类/方法"返回的数据转换为JSON对象
    @RestController用在类上,相当于@Controller+@ResponseBody

            注解选择:

                    请求参数有多个时,将多个参数写成json格式,后台以json格式接收,@RequestBody使用广泛

                    请求参数非json时,用@RequestParam接收

                    请求参数通常只有1个时,可以用@PathVariable接收 

    1.4 代码示例

    1. @Controller
    2. public class TeacherController {
    3. private static final Logger log = LoggerFactory.getLogger(TeacherController.class);
    4. @Autowired
    5. private TeacherService userService;
    6. @RequestMapping("/save")
    7. @ResponseBody
    8. public Teacher save(@RequestBody Teacher teacher) {
    9. teacher.setName("王五");
    10. teacher.setAge(44);
    11. teacher.setPosition("英语老师");
    12. log.info(String.valueOf(teacher));
    13. return teacher;
    14. }
    15. }

    2 REST风格

            REST(Representational State Transfer)表现层资源状态转换

            RESTful按照REST风格访问资源

    2.1 资源访问对比

            (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风格优点:书写简化,隐藏访问路径(更加安全)

    2.2 实现原理

            REST风格访问资源是用行为动作进行区分,可以用同一个请求路径,实现不同的功能

                    http://localhost/users/1    GET方式(查询),DELETE方式(删除)

                    http://localhost/users       POST方式(新增),PUT方式(修改)

    2.3 示例代码

            前端代码:

    1. addTeacher() {
    2. axios.post("/teachers", {
    3. position: '体育老师',
    4. name: '赵四',
    5. age: 54
    6. }, {
    7. headers: {
    8. 'Content-Type': 'application/json'
    9. }
    10. }).then(response => {
    11. alert(response.data)
    12. })
    13. },
    14. updateTeacher() {
    15. axios.put("/teachers", {
    16. position: '物理老师',
    17. name: '龙武',
    18. age: 77
    19. }, {
    20. headers: {
    21. 'Content-Type': 'multipart/form-data'
    22. }
    23. }).then(response => {
    24. alert(response.data)
    25. })
    26. },
    27. deleteTeacher(){
    28. axios.delete("/teachers/lisa/66", {
    29. }, {
    30. headers: {
    31. 'Content-Type': 'application/json'
    32. }
    33. }).then(response => {
    34. alert(response.data)
    35. })
    36. },
    37. queryTeacher(){
    38. axios.get("/teachers/gods", {
    39. }, {
    40. headers: {
    41. 'Content-Type': 'application/json'
    42. }
    43. }).then(response => {
    44. alert(response.data)
    45. })
    46. },
    47. queryAllTeacher(){
    48. axios.get("/teachers", {
    49. }, {
    50. headers: {
    51. 'Content-Type': 'application/json'
    52. }
    53. }).then(response => {
    54. alert(response.data)
    55. })
    56. }

            后台代码:

    1. @RestController
    2. @RequestMapping("/teachers")
    3. public class TeacherController {
    4. @Autowired
    5. private TeacherService teacherService;
    6. private static final Logger log = LoggerFactory.getLogger(TeacherController.class);
    7. @PostMapping
    8. public String add(@RequestBody Teacher teacher) {
    9. log.info("新增teacher信息为:" + teacher);
    10. return "{'info':'add success'}";
    11. }
    12. @PutMapping
    13. public String update(@RequestParam String position, @RequestParam String name, @RequestParam Integer age) {
    14. Teacher teacher = new Teacher();
    15. teacher.setPosition(position);
    16. teacher.setName(name);
    17. teacher.setAge(age);
    18. log.info("修改teacher为:" + teacher);
    19. return "{'info':'update success'}";
    20. }
    21. /**
    22. * {name}将"请求路径"倒数第二个作为路径变量
    23. * {age}将"请求路径"最后一个作为路径变量
    24. *
    25. * @PathVariable 接收名为id或age的路径变量
    26. */
    27. @DeleteMapping("/{name}/{age}")
    28. public String delete(@PathVariable String name, @PathVariable Integer age) {
    29. log.info("删除name为" + name + ",age为" + age + "的teacher");
    30. return "{'info':'delete success'}";
    31. }
    32. @GetMapping("/{name}")
    33. public String query(@PathVariable String name) {
    34. log.info("查询name为" + name + "的teacher");
    35. return "{'info':'query success'}";
    36. }
    37. @GetMapping
    38. public String queryAll() {
    39. log.info("查询全部的teacher");
    40. return "{'info':'query all success'}";
    41. }
    42. }

    3 放行访问

            因为所有的请求都会被Servlet容器拦截,而通过web配置类设置的又是将所有拦截的请求交给SpringMVC去处理,导致即使访问一些静态资源(html,css,js,img等)也会被拦截后交给SpringMVC处理,而SpringMVC通过请求路径映射又找不到对应的@RequestMaping,就会报404错误

            我们需要的是访问接口交给SpringMVC映射处理,访问静态资源放行,因此需要一个SpringMVESupport配置类继承WebMvcConfigurationSupport类,并重写addResourceHandlers方法

    1. /**
    2. * 放行资源访问
    3. * 此类需要被SpringIOC容器扫描到
    4. */
    5. @Configuration //注意此类虽然用@Configuration注解了,但要区别于Spring容器的@Configuration,所以不能在Spring配置类中用@Import引入这个类,也不能Spring配置类自己继承WebMvcConfigurationSupport,而只能单独使用这个类并加上@Configuration
    6. public class SpringMVCSupportConfig extends WebMvcConfigurationSupport {
    7. @Override
    8. protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    9. //被servlet拦截的"请求路径"如果是/html/**,不要被交给MVC处理,而是交给Tomcat处理(将/html/**请求放行,并用html目录下的资源去匹配)
    10. registry.addResourceHandler("/html/**").addResourceLocations("/html/");
    11. registry.addResourceHandler("/index.html").addResourceLocations("/index.html");
    12. }
    13. }
  • 相关阅读:
    在Spring中使用监听器以及事件监听机制
    面向对象【Package与Import】
    java注解反射之自定义Retrofit 项目实战
    Matlab:Matlab软件之Simulink的简介、特点、使用方法、界面介绍之详细攻略
    Java中使用alibaba easyexcel导出Excel,合并单元格
    EdgeX(10) :Xubuntu-22 linux系统安装EdgeX2.1相关服务,服务都比较小,下载启动速度快。
    DOM跟BOM的区别
    华为机试练习题:HJ51 输出单向链表中倒数第k个结点
    uni 结合vuex 编写动态全局配置变量 this.baseurl
    SOLIDWORKS 2024新产品发布会暨SOLIDWORKS 创新日活动-硕迪科技
  • 原文地址:https://blog.csdn.net/SunnerChen/article/details/133076220