文章目录
- SpringMVC
- 【原理】:
- 一、why?:
- 二、环境搭建(配置方式):
- ▶1.导入jar包
- ▶2.创建简单测试----创建Controller类继承AbstractController
- ▶3.如何读取Controller文件,创建SpringMVC.xml配置文件,映射Controller
- ▶4.在web.xml中读取SpringMVC.xml配置文件
- ▶5.项目加入Tomcat(Tomcat应该都配置好了,前期Maven有教程)。
- ▶6.此处没有项目,只是测试我们的Controller是否可以读取,springMVC配置是否完成
- 三、注解驱动控制器Controller(注解方式)
- ▶1.web.xml
- ▶2.SpringMVC.xml配置(头部关于context的命令)
- ▶3.Controller,不需要继承
- 四、关于@RequestMapping()
- 五、关于@RequestParam()传参
- 六、传对象
- 七、参数传递(作用域):
- 1.加注解@ModelAttribute
- 2.new ModelAndView()
- 3.model
- 4.map
- 5.@SessionAttributes
- 6.转发与重定向
- 八、@ResponseBody返回json数据
- 1.@JsonSerialize(include)空值不返回
- 2.@JsonSerialize(using)处理前后端对状态类字段不统一,需转换
- 3.关于Date时间数据类型格式化
- 九、视图解析器
- 十、REST风格
SpringMVC
springMVC是一种基于Java实现MVC模型的轻量级Web框架
- 是一种表现层框架技术
- 用于进行表现层功能开发
【原理】:
【原理每个人的理解不一样,面试考】
一、why?:
【重点解决的是servlet问题】
以前一个请求写一个servlet,违背了面向对象的原则,都是操作一个模块,却写了很多servlet,麻烦。
创建一个Controller类,请求多个方法,一个模块的执行可以写一个类文件。
二、环境搭建(配置方式):
▶1.导入jar包
<!--统一版本使用标签properties-->
<properties>
<spring.version>4.0.2.RELEASE</spring.version>
</properties>
<!--SpringMVC的jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--运行Toncat的时候会用到jsp,Controller根源还是servlet-->
<!--引入servlet jar包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--引入jsp jar包-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
▶2.创建简单测试----创建Controller类继承AbstractController
//创建IndexController.java类,继承AbstractController,会重写方法
public class IndexController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {
System.out.println("测试输出====");
//return返回的试图就是页面
return new ModelAndView("index.jsp");
}
}
▶3.如何读取Controller文件,创建SpringMVC.xml配置文件,映射Controller
命令空间有两个没有用到,后续会用的。-------看注释
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--映射Controller,不是new对象,不能用id,用name做路径-->
<!--在运行Controller时,name的名字就代表路径0---http://localhost:8080/indexController-->
<bean name="/indexController" class="com.jules.controller.IndexController"></bean>
</beans>
▶4.在web.xml中读取SpringMVC.xml配置文件
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--读取springmvc配置文件-->
<servlet>
<servlet-name>springMVC</servlet-name> <!--自定义名字-->
<!--前端控制器-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMVC.xml</param-value> <!--配置文件路径-->
</init-param>
<load-on-startup>1</load-on-startup> <!--项目启动时加载servlet-->
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
▶5.项目加入Tomcat(Tomcat应该都配置好了,前期Maven有教程)。
【▲注意:启动服务器,要想浏览器可以直接打开项目,下图:如果“/”后还有东西,在浏览器地址要加上“/”后面的名称。】
▶6.此处没有项目,只是测试我们的Controller是否可以读取,springMVC配置是否完成
三、注解驱动控制器Controller(注解方式)
上面我们发现执行Controller依旧很麻烦,所以项目一般使用注解进行
▶1.web.xml
和上面一样,它 是读取配置文件的,一直需要。
▶2.SpringMVC.xml配置(头部关于context的命令)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- <!–映射Controller,不是new对象,不能用id,用name做路径–>-->
<!-- <bean name="/indexController" class="com.hz.controller.IndexController"></bean>-->
<!--自动扫描的包名,只扫描@Controller -->
<context:component-scan base-package="com.hz.controller" />
<!--开启注解-->
<mvc:annotation-driven/>
</beans>
▶3.Controller,不需要继承
-
@Controller:标注一个普通的JavaBean成为可以处理请求的控制器
-
@RequestMapping:通过请求URL进行映射,可以写在方法上,也可以写在类上表示整个模块
@Controller //必须有
//@RequestMapping("/indexController")
public class IndexController {
//这样可以写多个方法====
//在方法上注解
//方法一:
@RequestMapping("/index")
public ModelAndView index() {
System.out.println("index方法~~~~");
return new ModelAndView("index.jsp");
}
//方法二:
@RequestMapping("/aaa")
public ModelAndView aaa() {
System.out.println("aaaa方法~~~~");
return new ModelAndView("index.jsp");
}
}
四、关于@RequestMapping()
-
▶标识在类上:标识这一个模块,区别两个模块中的重复方法
-
▶标识在方法上:作为路径
- 拥有属性method
method:
RequestMethod.GET------必须以GET方式进入 @GetMapping
RequestMethod.POST----必须以POST方式进入 @PostMapping
- 拥有属性method
-
▶传参:
@Controller @RequestMapping("/provider") public class ProviderController { @RequestMapping(value = "/index",method = RequestMethod.GET) //直接传参 public ModelAndView index(String proName,String proCode) { System.out.println("proName=="+proName); System.out.println("proCode=="+proCode); return new ModelAndView("/index.jsp"); } }
-
▶拥有属性params:请求参数的映射条件,指定请求的URL地址需要带那些参数:params={ “param1=value1” , “param2” , “!param3” --不传}
- 必须要传的值
@Controller @RequestMapping("/provider") public class ProviderController { //此时proName必须传 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"proName"}) public ModelAndView index(String proName,String proCode) { System.out.println("proName=="+proName); System.out.println("proCode=="+proCode); return new ModelAndView("/index.jsp"); } }
- 必须要传的值
五、关于@RequestParam()传参
- 属性value传递参数的别名;
- 属性required是否必须传此参数,默认false;
- 属性defaultValue设置默认值
必须传的值required = true与设置默认值defaultValue="0000"是冲突的
- 不管是Integer类型还是String类型,传递默认值都要加引号
public ModelAndView index(@RequestParam(value = "pName",required = true) String proName,
String proCode,
@RequestParam(value = "id",defaultValue = "1")Integer id) {
System.out.println("proName=="+proName);
System.out.println("proCode=="+proCode);
return new ModelAndView("/index.jsp");
}
六、传对象
要加入实体类
<!--简单的jsp页面,属性name的值与实体类对应-->
<body>
<form action="/provider/testProvider" method="post">
供应商编号:<input type="text" name="proCode" /><br/>
供应商名称:<input type="text" name="proName" /><br/>
<input type="submit" value="注册">
</form>
</body>
@RequestMapping(value = "/testProvider",method = RequestMethod.POST)
public ModelAndView saveProvider(Provider provider) {
System.out.println(provider.toString());
return new ModelAndView("/index.jsp");
}
七、参数传递(作用域):
【前四种是request域,最后一个是session作用域】
1.加注解@ModelAttribute
@Controller
public class IndexController {
@RequestMapping("/index1")
//uname放入request作用域
public ModelAndView index(@ModelAttribute("uname") String uname) {
System.out.println("uname==="+uname);
return new ModelAndView("/index.jsp");
}
}
2.new ModelAndView()
@Controller
public class IndexController {
@RequestMapping("/index2")
public ModelAndView index() {
//自定义数据放域
String msg = "这是IndexController类";
ModelAndView mv = new ModelAndView("/index.jsp");
mv.addObject("msg",msg);
//mv.setViewName("视图名");
return mv;
}
}
3.model
@RequestMapping("/index3")
public String index1(Model model)
{
model.addAttribute("user_name","张三");
return "/index.jsp";
}
4.map
@RequestMapping("/index4")
public String index2(Map<String ,Object> map){
map.put("user_name","789");
return "/index.jsp";
}
【注意:使用EL表达式加-----isELIgnored="false"】
//index.jsp 测试上面request作用域传值
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
<body>
<h2>首页~Hello World!</h2>
${uname} <br/>
${msg} <br/>
${user_name} <br/>
</body>
</html>
【开启服务器,访问 @RequestMapping("/index~")等路径测试作用域】
5.@SessionAttributes
【@SessionAttributes只能定义在类上,作用是将指定的Model中的键值对添加至session中】
- @SessionAttributes(types=User.class)会将model中所有类型为 User的属性添加到会话中。
- @SessionAttributes(value={“user1”, “user2”}) 会将model中属性名为user1和user2的属性添加到会话中。
- @SessionAttributes(types={User.class, Dept.class}) 会将model中所有类型为 User和Dept的属性添加到会话中。
- @SessionAttributes(value={“user1”,“user2”},types={Dept.class})会将model中属性名为user1和user2以及类型为Dept的属性添加到会话中。
@Controller
@SessionAttributes(value = {"name"}) //与Model中的键key保持一致
public class IndexController {
@RequestMapping("/index0")
public ModelAndView index0(String user_name){
ModelAndView mv = new ModelAndView("/index.jap");
//存入Request作用域和Session作用域
mv.addObject("name",user_name);
return mv;
}
}
在saveProvider.jsp获取数据测试数据是否保存在session中${name}
6.转发与重定向
【return默认是转发,重定向放在request的值拿不到 】
public String test(User user)
{
.....
return "redirect:/user.jsp"; //重定向
return "forward:页面"; //转发
}
八、@ResponseBody返回json数据
@ResponseBody这个注解通常使用在控制层(controller)的方法上,其作用是将方法的返回值以特定的格式写入到response的body区域,进而将数据返回给客户端。当方法上面没有写ResponseBody,底层会将方法的返回值封装为ModelAndView对象。
假如是字符串则直接将字符串写到客户端。如果返回String,默认按iso8859-1编码,页面可能出现乱码。因此在注解中我们可以手动修改编码格式,例如@RequestMapping(value=“/路径”,produces=“text/html;charset=utf-8”),前面是请求的路径,后面是编码格式。
假如是一个对象,此时会将对象转化为json串然后写到客户端,返回对象,按utf-8编码。
- 可以加在类上,下面的所有方法数据返回json
- 加在方法上,设置当前控制器方法响应内容为当前返回值,无需解析
- 使用前先导坐标
<!--JSON依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.3</version> </dependency>
- 使用类上的时候:@RestControlle相当于@Controller+@ResponseBody,直接使用@RestControlle即可。
@Controller
//@ResponseBody //给下面所有方法返回JSON
//@RestController //相当于@Controller+@ResponseBody
public class IndexController {
/**
* 对象返回JSON
* @return
*/
@RequestMapping("/findProviderJSON")
@ResponseBody //自动返回json
public Provider findProviderJSON() {
Provider provider= new Provider();
provider.setProCode("7811");
provider.setProName("三百七七");
return provider;
}
/**
* 集合返回对象
* @return
*/
@RequestMapping("/findProListJSON")
@ResponseBody //自动返回json,就不会返回页面
public List<Provider> findProListJSON(){
List<Provider> provider = new ArrayList<Provider>();
Provider provider1 = new Provider();
provider1.setProName("朱尔斯");
provider1.setCreationDate(new Date());
Provider provider2 = new Provider();
provider2.setProName("Jules");
provider2.setCreationDate(new Date());
provider.add(provider1);
provider.add(provider2);
return provider;
}
对象返回JSON
集合返回JSON
1.@JsonSerialize(include)空值不返回
【看测试图发现没有传的值会返回null,对象中添加@JsonSerialize(),表示空值null不返回】
实体类上添加:
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
表示属性为null不返回
2.@JsonSerialize(using)处理前后端对状态类字段不统一,需转换
【@JsonSerialize注解,主要用于数据转换,该注解作用在该属性的getter()方法上。】
【1.实体类上在需要装换的字段上加上注解】
/**
* 文字型状态值
*/
@JsonSerialize(using = MySerializerUtils.class)
private int status;
【2.负责转化的类的规则】
public class MySerializerUtils extends JsonSerializer<Integer> {
@Override
public void serialize(Integer status, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String statusStr = "";
switch (status) {
case 0:
statusStr = "暂存";
break;
case 1:
statusStr = "待上报";
break;
case 2:
statusStr = "待审核";
break;
case 3:
statusStr = "已审";
break;
case 4:
statusStr = "退回";
break;
case -1:
statusStr = "已删";
break;
default:
statusStr = "状态信息不符合";
}
jsonGenerator.writeString(statusStr);
}
}
http://www.qb5200.com/article/406882.html
3.关于Date时间数据类型格式化
时间格式化,否则是一串数字:
- @DateTimeFormat(pattern=" ") 入参时间格式化
- @JsonFormat(pattern=" ") 输出时间格式化
- timezone = “GMT+8”,我们在页面显示的时间与北京时间相差8个小时,加timezone处理时差
//@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //入参不乱
//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") //返回json的时候防止时间乱
@Setter
@Getter
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date creationDate; //创建时间
【但在项目中时间一般用String类型】
九、视图解析器
【在return路径的时候,我们可以省略“/”和“.jsp”,jsp文件名mv.setViewName("index") , 这就需要视图解析器的前缀后缀】
springMVC.xml中
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
//前缀:jsp文件所在的路径
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
看图理解前缀路径如何写的
十、REST风格
在我们访问一些网站的时候会发现,它的最后有一串数字,或者数字.html,这是如何实现的呢?
@Controller
@RequestMapping("/provider")
public class ProviderController {
@RequestMapping(value = "/jules/{id}.html")
public ModelAndView stylePage(@PathVariable("id") Integer id) {
System.out.println("id======"+id);
return new ModelAndView("index");
}
}
//请求路径为:http://localhost:8080/provider/jules/11.html
//@RequestMapping(value = "/jules/{id1}/{id}.html") 也可以传多个
【后缀显示html页面实际上是我们自己的风格,页面还是jsp而已~~】