spring系列 SpringMVC

本文详细介绍了SpringMVC的概念、创建web工程的Maven结构、配置Tomcat服务器插件,以及解决乱码问题。讲解了导包的重要性,特别是spring-webmvc和servlet-api的依赖。通过代码实例展示了如何配置SpringMVC环境、创建控制器类,以及处理请求参数和响应数据。还深入讨论了REST风格的URL设计,并给出相关案例。最后,探讨了静态资源的放行配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

SpringMVC是一种基于Java实现MVC模型的轻量级Web框架。

创建web工程(Maven结构)

设置tomcat服务器插件

tomcat7进行get请求时会有中文乱码问题(8.5版本后没有这个问题)这里要配置字符集:

<build>

    <plugins>

      <plugin>

        <groupId>org.apache.tomcat.maven</groupId>

        <artifactId>tomcat7-maven-plugin</artifactId>

        <version>2.1</version>

        <configuration>

          <port>80</port><!--tomcat端口号-->

          <path>/</path> <!--虚拟目录-->

          <uriEncoding>UTF-8</uriEncoding><!--访问路径编解码字符集-->

        </configuration>

      </plugin>

    </plugins>

  </build>

导包

<scope>provided</scope>是为了避免冲突

<scope>provided</scope>是Maven的一个依赖范围元素,它表示这个依赖在实际应用中由JVM或者容器提供,比如servlet api、spring等。这意味着在编译和测试时,这个依赖是可用的,但在运行时,Maven不会将它包含在最终的打包结果中,因为假设最终的环境已经提供了这个依赖。

例如,如果你正在编写一个基于Servlet API的web应用,你可能需要在编译和测试期间使用Servlet API,但是你不需要(也不应该)将它包含在你的war文件中,因为最终的运行环境(比如Tomcat)已经提供了这个API。

spring-webmvc坐标自动依赖spring相关坐标

<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数据时要导这个包:

<dependency>  

        <groupId>com.fasterxml.jackson.core</groupId>  

        <artifactId>jackson-databind</artifactId>  

        <version>2.9.0</version>

</dependency>

代码

@Configuration初始化SpringMVC环境(同Spring环境)

@ComponentScan加载SpringMVC对应的bean

在spring3.0后web-inf下的web.xml就可以被配置类替代了。

//spring不是一定要定义,写出来只是为了便于理解后面的bean多次加载问题

//@Configuration

//@ComponentScan

//public class SpringConfig {

//}

@Configuration

@ComponentScan("com.xxz.controller")

public class SpringMvcConfig {

}

创建SpringMVC控制器类(等同于Servlet功能)

SpringMVC中,/save这样的映射是放在一起统一管理的,并不是放在每一个bean里自己管理。

@ResponseBody在这里必须加,得告诉前端我给你的是body里的数据,而不是要跳转到哪个资源路径,如果返回的是字符串,那直接给前端,如果是对象或集合,那就转成json这种前端能识别的数据格式。功能由我们前面导入的json相关包的HttpMessageConvert接口定义。

@Controller

@RequestMapping("/user")

public class UserController {    

        @RequestMapping("/save")    

        @ResponseBody    

        public String save(@ ){        

                System.out.println("user save ...");        

                return "{'info':'springmvc'}";    

        }

}

createServletApplicationContext()是指定SpringMVC的容器,new AnnotationConfigWebApplicationContext();是创建SpringMVC的容器,

getServletMappings是指定进入web的容器中的请求中,哪些请求走SpringMVC,而/就表示全部

createRootApplicationContext()创建非SpringMVC的的容器对象,这里就是spring容器。

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {             protected WebApplicationContext createServletApplicationContext() {                         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();        

                ctx.register(SpringMvcConfig.class);        

                return ctx;    

        }    

        protected String[] getServletMappings() {        

                return new String[]{"/"};    

        }    

        protected WebApplicationContext createRootApplicationContext() {        

                 //AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();        

                //ctx.register(SpringConfig.class);        

                //return ctx;    

        }

}

简化写法:

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{    

        protected Class<?>[] getServletConfigClasses() {        

                return new Class[]{SpringMvcConfig.class};    

        }    

        protected String[] getServletMappings() {        

                return new String[]{"/"};    

        }    

        protected Class<?>[] getRootConfigClasses() {        

                return new Class[]{SpringConfig.class};    

        }

        // 配字符编码过滤器,解决post请求中文参数乱码问题。    

        protected Filter[] getServletFilters() {        

                CharacterEncodingFilter filter = new CharacterEncodingFilter();                         filter.setEncoding("utf-8");        

                return new Filter[]{filter};    //多个过滤器用,分隔就行

        }

}

运行

找到Idea上面的Application处,搜mavan,在下方填command line写tomcat,选run选项的。

拓展

bean重复加载问题

spring和SpringMVC都指定了componentscan,都指定了扫描包,都会把bean加载出来,当一个bean在两个范围中时,都会加载一遍。

所以要想办法避免,最简单的非代码方式是将两config类挪位置,比如本来在com.xxx,那么可以挪到com或com的上一级。

代码手段:

在spring容器中,采取过滤器的方式,采用注解过滤的方式,过滤掉带@Controller的文件

@Configuration

@ComponentScan(value = "com.itheima",    

        excludeFilters = @ComponentScan.Filter(        

                type = FilterType.ANNOTATION,        

                classes = Controller.class    

        )

)

public class SpringConfig {

}

请求参数接收问题

地址栏后面拼接的参数:

普通参数:接口参数名与请求的参数一致的自动映射接收

POJO类型参数:bean属性名与请求的参数一致的自动映射接收

嵌套POJO类型参数:请求参数采取bean对象成员属性.对象成员属性的方式请求

        如果在嵌套关系中,被引用的对象成员名为A,那就是A.A的对象成员属性

数组类型参数:请求的参数名多写几个就行

        接口的接收方法(String[] names)

集合类型参数:框架看到List以为是个引用类型,要帮我们创建对象,但List是接口,没有构造,所以会报init错误,前面加上@RequestParam让框架直接装数据就行了,不在这里进行对象创建。

        接口的接收方法(@RequestParam List<String> names)

日期数据:?date=2088/08/08&date1=2088-08-18&date2=2088/08/28 8:08:08  

yyyy/MM/dd格式是默认可以接收的,所以直接:接口的接收方法(Date date)

另外的不是,要加:@DateTimeFormat,由spring-core的Convert接口定义的方法:

 接口的接收方法(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1)

 接口的接收方法(@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date2)

body中的json请求数据:

postman中的位置:body/raw/json

@EnableWebMvc作用是将请求的json转成对象(自动类型转换)

@Configuration

@ComponentScan("com.itheima.controller")

@EnableWebMvc

public class SpringMvcConfig {

}

接收请求中的json数据:@RequestBody

接口的接收方法(@RequestBody List<String> names)

接口的接收方法(@RequestBody Pojo pojp)

接口的接收方法(@RequestBody List<User> list)

@RequestBody与@RequestParam区别 :

@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】 @RequestBody用于接收json数据【application/json】

非json格式数据,选用@RequestParam接收请求参数。

后面开发以json格式数据为主,@RequestBody应用范围更广。

响应

响应文本数据

@ResponseBody不加的话,返回的字符串会被当做跳转地址

@RequestMapping("/toText")

@ResponseBody

public String toText(){

    System.out.println("返回纯文本数据");

    return "response text";

}

响应POJO对象

@RequestMapping("/toJsonPOJO")

@ResponseBody

public User toJsonPOJO(){

    System.out.println("返回json对象数据");

    User user = new User();

    user.setName("xxz");

    user.setAge(15);

    return user;

}

响应POJO集合对象

@RequestMapping("/toJsonList")

@ResponseBody

public List<User> toJsonList(){

    System.out.println("返回json集合数据");

    User user1 = new User();

    user1.setName("名字");

    user1.setAge(15);

    User user2 = new User();

    user2.setName("名字");

    user2.setAge(12);

    List<User> userList = new ArrayList<User>();

    userList.add(user1);

    userList.add(user2);

    return userList;

}

REST风格

原来访问路径形式:

        http://localhost/user/getById?id=1

        http://localhost/user/saveUser

REST风格访问路径形式:

        http://localhost/user/1

        http://localhost/user

隐藏了接口的部分信息(请求方式和参数名),更加简洁。

多种请求方式如GET、PUT、POST等,对同一个路径的请求还可以用来访问不同的接口。

案例

在Controller中定义方法时设定http请求方式"和请求请求参数(路径变量

@Controller

public class UserController {

    //当前请求方法为POST,表示REST风格中的添加操作

    @RequestMapping(value = "/users",method = RequestMethod.POST)

    @ResponseBody

    public String save(){

        System.out.println("user save...");

        return "{'module':'user save'}";

    }

    //当前请求方法为DELETE,表示REST风格中的删除操作

    //@PathVariable注解用于绑定路径参数与处理器方法形参间的关系,并且占位符名称与方法形参名称相同

    @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)

    @ResponseBody

    public String delete(@PathVariable Integer id){

        System.out.println("user delete..." + id);

        return "{'module':'user delete'}";

    }

    //当前请求方法为PUT,表示REST风格中的修改操作

    @RequestMapping(value = "/users",method = RequestMethod.PUT)

    @ResponseBody

    public String update(@RequestBody User user){

        System.out.println("user update..."+user);

        return "{'module':'user update'}";

    }

    //当前请求方法为GET,表示REST风格中的查询操作

    //@PathVariable注解用于设置路径变量(路径参数),要求路径上设置对应的占位符,并且占位符名称与方法形参名称相同

    @RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)

    @ResponseBody

    public String getById(@PathVariable Integer id){

        System.out.println("user getById..."+id);

        return "{'module':'user getById'}";

    }

    //当前请求方法为GET,表示REST风格中的查询操作

    @RequestMapping(value = "/users",method = RequestMethod.GET)

    @ResponseBody

    public String getAll(){

        System.out.println("user getAll...");

        return "{'module':'user getAll'}";

    }

}

简化写法:

@RestController     //使用@RestController注解替换@Controller与@ResponseBody注解,简化书写

@RequestMapping("/books")

public class BookController {

//    @RequestMapping( method = RequestMethod.POST)

    @PostMapping//使用@PostMapping简化Post请求方法对应的映射配置

    public String save(@RequestBody Book book){

        System.out.println("book save..." + book);

        return "{'module':'book save'}";

    }

//    @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)

    @DeleteMapping("/{id}")  //使用@DeleteMapping简化DELETE请求方法对应的映射配置

    public String delete(@PathVariable Integer id){

        System.out.println("book delete..." + id);

        return "{'module':'book delete'}";

    }

//    @RequestMapping(method = RequestMethod.PUT)

    @PutMapping   //使用@PutMapping简化Put请求方法对应的映射配置

    public String update(@RequestBody Book book){

        System.out.println("book update..."+book);

        return "{'module':'book update'}";

    }

//    @RequestMapping(value = "/{id}" ,method = RequestMethod.GET)

    @GetMapping("/{id}")    //使用@GetMapping简化GET请求方法对应的映射配置

    public String getById(@PathVariable Integer id){

        System.out.println("book getById..."+id);

        return "{'module':'book getById'}";

    }

//    @RequestMapping(method = RequestMethod.GET)

    @GetMapping      //使用@GetMapping简化GET请求方法对应的映射配置

    public String getAll(){

        System.out.println("book getAll...");

        return "{'module':'book getAll'}";

    }

}

静态资源放行:

@Configuration

public class SpringMvcSupport extends WebMvcConfigurationSupport {

    //设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载

    @Override

    protected void addResourceHandlers(ResourceHandlerRegistry registry) {

        //当有请求访问/pages/**时候,从/pages目录下查找内容

        registry.addResourceHandler("/pages/**")

            .addResourceLocations("/pages/");

        registry.addResourceHandler("/js/**")

            .addResourceLocations("/js/");              

        registry.addResourceHandler("/css/**")

            .addResourceLocations("/css/");      

        registry.addResourceHandler("/plugins/**")

            .addResourceLocations("/plugins/");

    }

}

在主配置上添加扫描:

@Configuration

@ComponentScan({"com.itheima.controller","自定义的SpringMvcSupport 所在的包路径"})

@EnableWebMvc

public class SpringMvcConfig {

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呀吼呀吼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值