数据结构与算法之美 下栽: www.sanzhishu.top/655.html
SpringMVC
Spring集成web环境
集成步骤
- 导入相关的坐标,spring的和web的
org.springframework
spring-context
5.3.6
mysql
mysql-connector-java
5.1.32
c3p0
c3p0
0.9.1.2
cn.6tail
nlf-mini-plugin-druid
1.0.0
junit
junit
4.12
test
org.springframework
spring-test
5.3.6
org.junit.jupiter
junit-jupiter
RELEASE
compile
junit
junit
RELEASE
compile
javax.servlet
javax.servlet-api
4.0.1
javax.servlet.jsp
javax.servlet.jsp-api
2.3.3
- 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:
com.myspring.listener.ContextLoader
contextConfigLocation
classpath:applicationContext.xml
Spring提供的获得应用上下文的工具
没错,上面又白写了。。。
上面的不用手动实现。Spring提供了一个监听器ContextLoaderListener就是对该功能的封装
我们只需要做两件事:
- 在web.xml中配置ContextLoaderListener监听器(需要先导入spring-web坐标) pom.xml:
org.springframework
spring-web
5.3.6
web.xml:
org.springframework.web.context.ContextLoaderListener
- 通过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
org.springframework
spring-webmvc
5.3.6
- 配置servlet在web.xml
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
DispatcherServlet
/
- 编写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创建)
- 发送请求测试
流程:
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");
### SpringMVC配置解析
在上面的代码中,最后我们renturn了jsp页面
```java
return "success.jsp";
//实际上本句为
return "forword:success.jsp";
//forword在本处意思为转发(不改变url地址访问资源),默认为forword
return "redirect:/success.jsp"
//redirect:代表重定向
我们还可以在springmvc中配置视图解析器,来避免写前缀后缀
这样一来我们可以这样写:
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中
这个isELIgnored="false"表示el表达式可用
Hello World!${username}
回写数据
- 直接返回字符串 在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转换工具坐标:
com.fasterxml.jackson.core
jackson-core
2.11.4
com.fasterxml.jackson.core
jackson-databind
2.11.4
com.fasterxml.jackson.core
jackson-annotations
2.11.4
springmvc不需要我们自己来转json字符串,有更加简便的方式:
返回对象和集合。
首先需要我们在spring配置文件中进行一些配置(配置处理器映射器):
控制类中:
@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"
其他两个不行
</mvc:annotation-driven>
SpringMVC获取请求数据
获取请求参数
- 获取基本类型参数:直接通过参数获得:
@RequestMapping("/quick")
@ResponseBody
public void save(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
url: 结果:
2. 获得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 getStringList() {
return stringList;
}
public void setStringList(List stringList) {
this.stringList = stringList;
}
private List 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 userList) throws IOException {
System.out.println(userList);
}
开放静态资源;
无法访问的js文件等静态资源是配置
这样也可以:在springmvc找不到资源是交给tomcat处理
解决低版本tomcat请求数据为中文乱码问题
如果tomcat版本较低,当配置post请求时,数据为中文会出现乱码,所以我们通过配置过滤器来解决
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
CharacterEncodingFilter
/*
参数绑定注解@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 {
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;
}
}
- 在配置文件中声明转换器
- 在中引用转换器
结果:
获得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坐标
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.5
- 配置文件上传解析器
- 编写文件上传代码
@RequestMapping("/quick")
@ResponseBody
//参数名必须与上传文件表单的各项name相同
public void save(String username, MultipartFile uploadFile) throws IOException {
// 获得文件名称
String originalFilename = uploadFile.getOriginalFilename();
// 保存文件到
uploadFile.transferTo(new File("D:\\"+originalFilename));
多文件上传同理:
@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));
}
当然也可以把参数换成一个数组
关注夏壹分享发送:资源 获取深入讲解JVM虚拟机课程