前后端分离

传统的mvc,view的生成其实是在服务器端生成的,或者页面跳转实在服务器端操纵的。

前后端分离,前后端之间的所有交互都是数据。前端自己实现路由,前端需要展示的数据则由后端提供。

前后端分离

        之前做过车联网的一个项目。客户端有Android,iOS,PC客户端,浏览器等,使用的是Restful。当时刚毕业,知道这种模式强大,但却不知道这就是前后端分离的一个案例。如下图

REST

rest简介

REST是一种交互方式,Restful则是符合rest原则的风格框架

无状态。每次请求不受上一次或者下一次请求影响

面向资源。这里的资源即数据,事实上,狭义的讲,就是一个URI。

如果一个架构复核REST原则,那么它就是一个Restful框架

共6中请求:PUT DELETE GET POST HEAD OPTIONS

如果URI相同,但是请求方式不同,那么处理的方法也不同

用uri定位资源,用http method定义操作

实现REST架构

1.前端统一返回json数据格式

1

{

2

success : true,

3

message:'',

4

code:'',

5

data : {}

6

}

2.后端统一对应的返回实体

1

2

import org.apache.ibatis.exceptions.TooManyResultsException;

3

4

import java.sql.SQLException;

5

/**

6

* 增删改时返回前端的判断实体

7

* @author Lihhz 2017-03-15

8

*

9

*/

10

public class ResponseState {

11

/**错误信息*/

12

protected String message;

13

/**错误编码*/

14

protected short code;

15

/**是否成功*/

16

protected boolean success;

17

/**返回数据*/

18

protected Object data;

19

20

public ResponseState() {

21

this.code = 0;

22

this.success = true;

23

this.data = null;

24

}

25

26

public ResponseState(String message) {

27

this.message = message;

28

}

29

30

public ResponseState(short code, String message) {

31

this.code = code;

32

this.message = message;

33

}

34

35

public ResponseState(boolean success, String message) {

36

this.success = success;

37

this.message = message;

38

}

39

40

public ResponseState(short code, boolean success, String message) {

41

this.code = code;

42

this.success = success;

43

this.message = message;

44

}

45

46

public ResponseState(Exception ex) {

47

this.code = -1;

48

this.success = false;

49

if (ex.getMessage() == null) {

50

this.message = "参数不正确或不完整";

51

} else if (ex.getCause() instanceof SQLException)

52

this.message = "服务器异常:执行数据库语句错误";

53

else if(ex.getCause() instanceof TooManyResultsException)

54

this.message = "应该查询出一条结果,但查询出多条结果.";

55

else

56

setMessage(ex.getMessage());

57

}

58

59

public String getMessage() {

60

return this.message;

61

}

62

63

public void setMessage(String message) {

64

if (message != null)

65

message = message.replace("\"", "'").replace('\r', '\0');

66

this.message = message;

67

}

68

69

public short getCode() {

70

return this.code;

71

}

72

73

public void setCode(short code) {

74

this.code = code;

75

}

76

77

public boolean getSuccess() {

78

return this.success;

79

}

80

81

public void setSuccess(boolean success) {

82

this.success = success;

83

}

84

85

public Object getData() {

86

return this.data;

87

}

88

89

public void setData(Object data) {

90

this.data = data;

91

}

92

93

public String toString() {

94

StringBuffer sbJson = new StringBuffer("{\"code\":");

95

sbJson.append(this.code).append(",\"message\":\"").append(this.message)

96

.append("\",").append("\"success\":").append(this.success)

97

.append("}");

98

return sbJson.toString();

99

}

100

}

3.数据格式转换

前端的json如何转化为后端的entity,后端的entity又如何转前端json

在spring mvc中提供一种转换方式

1

@ResponseBody

2

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

3

public PageVO query(HttpServletRequest request) {

4

……

5

}

其中RequestBody负责前端数据转后端,而ResponseBody则反之。如果使用@RestController而不是@Controller则不需要在方法上使用ResponseBody。下边是RestController的源码

1

/*

2

* Copyright 2002-2014 the original author or authors.

3

*

4

* Licensed under the Apache License, Version 2.0 (the "License");

5

* you may not use this file except in compliance with the License.

6

* You may obtain a copy of the License at

7

*

8

*      http://www.apache.org/licenses/LICENSE-2.0

9

*

10

* Unless required by applicable law or agreed to in writing, software

11

* distributed under the License is distributed on an "AS IS" BASIS,

12

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

13

* See the License for the specific language governing permissions and

14

* limitations under the License.

15

*/

16

17

package org.springframework.web.bind.annotation;

18

19

import java.lang.annotation.Documented;

20

import java.lang.annotation.ElementType;

21

import java.lang.annotation.Retention;

22

import java.lang.annotation.RetentionPolicy;

23

import java.lang.annotation.Target;

24

25

import org.springframework.stereotype.Controller;

26

27

/**

28

* A convenience annotation that is itself annotated with {@link Controller @Controller}

29

* and {@link ResponseBody @ResponseBody}.

30

* <p>

31

* Types that carry this annotation are treated as controllers where

32

* {@link RequestMapping @RequestMapping} methods assume

33

* {@link ResponseBody @ResponseBody} semantics by default.

34

*

35

* @author Rossen Stoyanchev

36

* @author Sam Brannen

37

* @since 4.0

38

*/

39

@Target(ElementType.TYPE)

40

@Retention(RetentionPolicy.RUNTIME)

41

@Documented

42

@Controller

43

@ResponseBody

44

public @interface RestController {

45

46

/**

47

* The value may indicate a suggestion for a logical component name,

48

* to be turned into a Spring bean in case of an autodetected component.

49

* @return the suggested component name, if any

50

* @since 4.0.1

51

*/

52

String value() default "";

53

54

}

55

在spring中配置jackson进行json的序列化操作

1

<bean id="dateFormat" class="java.text.SimpleDateFormat">

2

<constructor-arg value="yyyy-MM-dd HH:mm:ss" />

3

</bean>

4

5

<!-- 也可以自定义ObjectMapper继承自org.codehaus.jackson.map.ObjectMapper,做一些特殊处理。-->

6

<bean id="objectMapper" class="org.codehaus.jackson.map.ObjectMapper">

7

<property name="dateFormat" ref="dateFormat" />

8

</bean>

9

<!-- 注册RequestMappingHandlerMapping 和RequestMappingHandlerAdapter 两个bean。-->

10

<mvc:annotation-driven>

11

<mvc:message-converters>

12

<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">

13

<property name="objectMapper" ref="objectMapper">

14

</property>

15

</bean>

16

</mvc:message-converters>

17

</mvc:annotation-driven>

至此,一个简单的Restful风格的框架就搭建起来了。还有安全验证,异常处理,跨域等问题需要处理。