SpringMVC
Spring集成web环境
集成步骤
-
导入相关的坐标,spring的和web的
<dependencies> <!-- spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.6</version> </dependency> <dependency> <!-- mysql--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!-- 数据源一:c3p0--> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- 数据源二:druid--> <dependency> <groupId>cn.6tail</groupId> <artifactId>nlf-mini-plugin-druid</artifactId> <version>1.0.0</version> </dependency> <!-- junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring集成junit坐标:--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.6</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <!-- servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- jsp--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> </dependency> </dependencies>
-
spring相关配置
-
添加一个web包,用来写javaweb
-
在web.xml配置相关类
-
配置tomcat,部署项目运行
ApplicationContext应用上下文的获取方式
之前每次我们都是通过new的方式创建的应用上下文,这样的弊端是在大项目中配置文件会加载多次,应用上下文被创建多次,繁琐且不节省资源
所以我们运用监听器来只创建一次,所有的用这一个容器,所以:
创建一个实现ServletContext监听器的类:
public class ContextLoader implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//将这个应用上下文对象存储在servletContext域中
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("app",app);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
web层中:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
UserService userService= app.getBean(UserService.class);
userService.save();
}
web.xml:
<!--配置监听器-->
<listener>
<listener-class>com.myspring.listener.ContextLoader</listener-class>
</listener>
<!--配置全局参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
Spring提供的获得应用上下文的工具
没错,上面又白写了。。。
上面的不用手动实现。Spring提供了一个监听器ContextLoaderListener就是对该功能的封装
我们只需要做两件事:
-
在web.xml中配置ContextLoaderListener监听器(需要先导入spring-web坐标)
pom.xml:
<!-- spring-web--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.6</version> </dependency>
web.xml:
<!--配置监听器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
-
通过WebApplicationCintextUtils(一个客户端工具)获得应用上下文对象ApplicationContext
web层中:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = req.getServletContext(); //关键 WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext); UserService userService= app.getBean(UserService.class); userService.save(); }
SpringMVC简介
-
SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于SpringFrameWork的后续产品,已经融合在 Spring Web Flow 中。 SpringMVC已经成为目前最主流的MVC框架之一。
-
SpringMVC的作用:作为前端控制器,控制请求的共有行为,在传统的JavaEE技术中,只使用Servlet作为控制器,当每个功能都需要一个servlet程序相似功能也无法分开封装,另外,传统的开发模式也存在其它使用不便利的做法。
SpringMVC解决了V-C交互的问题,即V(View:视图)和C(Controller:控制器)之间的交互问题,具体表现在:用户可以通过视图将请求数据提交给服务器端的控制器,而控制器可以接收到相关数据后进行处理,最终,给予客户端某个视图,使得客户端得到响应结果。当然springMVC作为控制器还是需要servlet
SpringMVC开发步骤
-
导入SpringMVC
<!-- spring-mvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.6</version> </dependency>
-
配置servlet在web.xml
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 告诉控制层配置文件位置--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 服务器加载时就启动本servlet--> <!-- 当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;--> <!-- 当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。--> <!-- 正数的值越小,启动该servlet的优先级越高。--> <load-on-startup></load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <!-- 所有请求都会经过servlet--> <url-pattern>/</url-pattern> </servlet-mapping>
-
编写pojo(controller)
-
将controller使用注解(@Controller)配置到Spring容器中
//表明是一个控制类bean实例 @Controller public class UserController { //地址映射,当跳转/quick,访问此方法 @RequestMapping("/quick") public String save(){ System.out.println("Controller save running"); // 要跳转的视图 return "success.jsp"; } }
-
配置组件扫描(配置到Spring-mvc.xml:springmvc的配置文件,需要自己在resources创建)
<!-- 组件扫描:扫描controller--> <context:component-scan base-package="com.myspring.controller"/>
-
发送请求测试
流程:
SpringMVC的组件解析
SpringMVC内部执行流程
SpringMVC注解解析
@RequestMapping(“”):地址映射
常用参数:value:就是路径
method:可以指定请求方式。值为枚举方式在RequestMethod
params:指定请求参数条件,例如:
@Controller
@RequestMapping("/user")
public class UserController {
//当地址为localhost:8080/user/quick时访问该方法
@RequestMapping("/quick")
public String save(){
System.out.println("Controller save running");
// 要跳转的视图:localhost:8080/user/success.jsp,当前的前一级目录下的该资源(/success.jsp.就代表当前web应用下,即webapp目录下)
return "success.jsp";
}
}
SpringMVC配置解析
在上面的代码中,最后我们renturn了jsp页面
return "success.jsp";
//实际上本句为
return "forword:success.jsp";
//forword在本处意思为转发(不改变url地址访问资源),默认为forword
return "redirect:/success.jsp"
//redirect:代表重定向
我们还可以在springmvc中配置视图解析器,来避免写前缀后缀
<!-- 配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀-->
<property name="prefix" value="/jsp/"></property>
<!-- 后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
这样一来我们可以这样写:
return "/success"
代表:/jsp/success.jsp
总结:
SpringMVC的数据响应
SpringMVC的数据响应方式:
- 页面跳转
- 直接返回字符串
- 通过ModelAndView对象返回
- 回写数据
- 直接返回字符串
- 返回对象或集合
页面跳转
-
直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转:不多说,上面例子就是用的这种
-
通过ModelAndView对象返回
@RequestMapping("/quick2") public ModelAndView save2(){ ModelAndView modelAndView = new ModelAndView(); // 设置模型数据:可以在jsp中通过el表达式获得 modelAndView.addObject("username","lihua"); // 设置视图名称 modelAndView.setViewName("index.jsp"); return modelAndView; } //这种也可以,和上面一样只不过是springmvc为你注入了一个bean实例 @RequestMapping("/quick2") public ModelAndView save2(ModelAndView modelAndView){ // 设置模型数据 modelAndView.addObject("username","lihua"); // 设置视图名称 modelAndView.setViewName("index"); return modelAndView; }
返回字符串的形式也可以传递参数:
@RequestMapping("/quick")
public String save(Model model){
model.addAttribute("username","lihua");
// 要跳转的视图
return "success";
}
//另外代替Model,还可以传HttpServletRequest等作为参数
在index.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
这个isELIgnored="false"表示el表达式可用
<html>
<body>
<h2>Hello World!${username}</h2>
</body>
</html>
回写数据
-
直接返回字符串
在web阶段我们需要回写字符串直接response.getWriter().print(“hello world”),在Controller直接通过参数注入response对象,但是还有更加简单的方法:返回字符串
@RequestMapping("/quick") //告知springmvc返回的用于回写数据的字符串,不要进行页面跳转 @ResponseBody public String save(HttpServletResponse response){ return "helloworld"; }
-
返回对象或集合
当我们需要传递一个对象或者集合时,可以先转成json格式字符串再return
@RequestMapping("/quick") // 还是要写这个注解,因为还是返回的字符串数据 @ResponseBody public String save(HttpServletResponse response) throws IOException { UserServiceImpl userService = new UserServiceImpl(); userService.setAge(10); userService.setName("lihua"); // 使用json转换工具将对象转换为json格式字符串再返回 ObjectMapper objectMapper = new ObjectMapper(); String string = objectMapper.writeValueAsString(userService); return string;
需要导入的json转换工具坐标:
<!-- json工具核心--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.11.4</version> </dependency> <!-- json数据绑定--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.4</version> </dependency> <!-- json和注解相关--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.11.4</version> </dependency>
springmvc不需要我们自己来转json字符串,有更加简便的方式:
返回对象和集合。
首先需要我们在spring配置文件中进行一些配置(配置处理器映射器):
<!-- 配置处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
</list>
</property>
</bean>
控制类中:
@RequestMapping("/quick")
// 还是要写这个注解,因为还是返回的字符串数据
@ResponseBody
public UserServiceImpl save(HttpServletResponse response) throws IOException {
UserServiceImpl userService = new UserServiceImpl();
userService.setAge(10);
userService.setName("lihua");
return userService;
}
配置太麻烦了,可以通过mvc的注解驱动代替上述配置,没错,又又又有更加简便的操作:
在springmvc的配置文件中:
<!-- mvc注解驱动-->
<mvc:annotation-driven/>
注意:注解驱动对应的命名空间必须是
xmlns:mvc="http://www.springframework.org/schema/mvc"
其他两个不行
SpringMVC获取请求数据
获取请求参数
-
获取基本类型参数:直接通过参数获得:
@RequestMapping("/quick") @ResponseBody public void save(String username,int age) throws IOException { System.out.println(username); System.out.println(age); }
url:
结果:
-
获得pojo类型参数:pojo参数的属性名和请求参数的name一致,参数值会自动映射匹配
@Controller public class UserController { private int age; private String name; // 还需要getter和setter public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @RequestMapping("/quick") @ResponseBody public void save(UserController userController) throws IOException { System.out.println(userController.getAge()); System.out.println(userController.getName()); } }
输入与结果:
- 获得数组类型参数:和基本数据类型完全一致,函数参数和请求的参数一致就可以
-
获得集合类型参数:需要被包装到一个pojo类中才可以
public class VO { public List<String> getStringList() { return stringList; } public void setStringList(List<String> stringList) { this.stringList = stringList; } private List<String> stringList; }
@RequestMapping("/quick")
@ResponseBody
public void save(VO vo) throws IOException {
System.out.println(vo.getStringList());
}
当请求为Ajax可以通过指定contenttype为json格式,通过注解直接获取集合数据:
ajax:
@RequestMapping("/quick")
@ResponseBody
public void save(@RequestBody List<String> userList) throws IOException {
System.out.println(userList);
}
开放静态资源;
无法访问的js文件等静态资源是配置
<!-- 开放资源的访问权限:请求为mapping时开放location的静态资源-->
<mvc:resources mapping="js/**" location="/js/"></mvc:resources>
这样也可以:在springmvc找不到资源是交给tomcat处理
<mvc:default-servlet-handler/>
解决低版本tomcat请求数据为中文乱码问题
如果tomcat版本较低,当配置post请求时,数据为中文会出现乱码,所以我们通过配置过滤器来解决
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
参数绑定注解@requestParam
当请求的参数名称和controller方法参数不一致时,就需要通过@requestParam注解显示
@RequestMapping("/quick")
@ResponseBody
//当我在url中输入的是name
public void save(@RequestParam("name") String username) throws IOException {
System.out.println(username);
}
@requestParam注解的参数:
获得Restful风格的参数
Restful是一种软件架构风格、设计风格,而不是标准,只是提供一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更加简洁,更有层次等
HTTP协议中四个表示操作方式的动词:
具体实例:
自定义类型转换器
SpringMVC实际上已经具备了一些常用的类型转换器,例如客户端提交的字符串被转换成int型进行参数设置
但是可能并不完全满足我们的需求,所以我可以自定义类型转换器:
开发步骤:
-
定义转换器实现Converter接口
public class DataConverter implements Converter<String,Date> { public Date convert(String dateStr) { //将日期字符串转换为日期对象 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = format.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } return date; } }
-
在配置文件中声明转换器
<!-- 声明这个转换器--> <bean id="ConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.myspring.converter.DataConverter"></bean> </list> </property> </bean>
-
在
中引用转换器 <!-- 配置处理器映射器--> <mvc:annotation-driven conversion-service="ConversionService"/>
结果:
获得Servlet的相关API
前面说过,直接在相关方法参数位置注入,就不在赘述
获取请求头
-
使用@RequestHeader
@RequestMapping("/quick") @ResponseBody // 将请求头的user-agent一行赋值给参数 public void save(@RequestHeader(value = "User-Agent") String userAgent) throws IOException { System.out.println(userAgent); }
-
@CookieValue获得Cookie的值:
@RequestMapping("/quick")
@ResponseBody
// 通过cookie的id获得cookie的值
public void save(@CookieValue(value = "JSESSIONID") String cookie) throws IOException {
System.out.println(cookie);
}
文件上传
文件上传客户端要求:
单文件上传步骤:
-
导入fileupload和io坐标
<!-- fileupload--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!-- commons-io--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
-
配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上传文件总大小最大--> <property name="maxUploadSize" value="5242800"/> <!-- 上传单个文件大小最大--> <property name="maxUploadSizePerFile" value="5242800"/> <!-- 生成文件编码类型--> <property name="defaultEncoding" value="UTF-8"/> </bean>
-
编写文件上传代码
@RequestMapping("/quick") @ResponseBody //参数名必须与上传文件表单的各项name相同 public void save(String username, MultipartFile uploadFile) throws IOException { // 获得文件名称 String originalFilename = uploadFile.getOriginalFilename(); // 保存文件到 uploadFile.transferTo(new File("D:\\"+originalFilename));
我在创建multipartResolver
多文件上传同理:
@RequestMapping("/quick")
@ResponseBody
//参数名必须与上传文件表单的各项name相同
public void save(String username, MultipartFile uploadFile1,MultipartFile uploadFile2) throws IOException {
// 获得文件名称
String originalFilename = uploadFile1.getOriginalFilename();
String originalFilename2 = uploadFile2.getOriginalFilename();
// 保存文件到
uploadFile2.transferTo(new File("D:\\"+originalFilename));
uploadFile1.transferTo(new File("D:\\"+originalFilename));
}
当然也可以把参数换成一个数组
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/195246.html