spring学习(一)—— spring mvc
目的
了解Spring mvc
学习对象
https://github.com/spring-projects/spring-mvc-showcase
学习收获
1. 自定义注解
// 以下是注解接口
Target(value={ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MaskFormat { String value(); }
// 以下是使用注解
@MaskFormat("(###) ###-####")
private String masked;
2. RequestMapping注解
- 可修饰类 和 方法,对应的url按层级累加
- 可指定Get/Post方法
@Controller @RequestMapping("/data") public class RequestDataController { @RequestMapping(value="param", method=RequestMethod.GET) public @ResponseBody String withParam(@RequestParam String foo) { // 对应url /data/param?foo=bar return "Obtained 'foo' query parameter value '" + foo + "'"; } @RequestMapping(value="path/{var}", method=RequestMethod.GET) public @ResponseBody String withPathVariable(@PathVariable String var) { // 对应url /data/path/bar return "Obtained 'var' path variable value '" + var + "'"; } } @Controller public class MappingController { @RequestMapping("/mapping/path") public @ResponseBody String byPath() { // 最常见的 return "Mapped by path!"; } @RequestMapping(value="/mapping/path/*", method=RequestMethod.GET) public @ResponseBody String byPathPattern(HttpServletRequest request) { // 模式匹配到一组 url return "Mapped by path pattern ('" + request.getRequestURI() + "')"; } }
3. java bean就是基础的对象类,每个属性可通过注解添加限制,也可用于json的转化
@XmlRootElement public class JavaBean { @NotNull private String fruit;
@NotEmpty // 非空 private String name; @Min(21) // 限定取值范围 private int age; @DateTimeFormat(iso=ISO.DATE) @Past // 必须是过去的时间,相反的是 Future private Date birthDate; @MaskFormat("(###) ###-####") // 自定义的格式 private String phone; @NumberFormat(style=Style.PERCENT) private BigDecimal percent; public JavaBean() { // 构造方法1 } public JavaBean(String foo) { // 构造方法2 this.foo = foo; } @Override public String toString() { // java bean作为最基础的对象类,一般会重构toString方法 return "JavaBean {foo=[" + foo + "]]}"; } } // 一些场景下(如调用接口)可通过序列化的对象 根据java bean定义反转义回来 String json = MapUtils.getString(params,"json"); JavaBean aBean = JsonUtil.toObject(json, JavaBean.class);
4. 通过mock测试页面访问 或者 调用其他第三方服务
日常项目中,不可避免会涉及多个系统的交互,如前后端的交互、多个后端系统间的交互、子系统间的交互。为了避免开发进度受上游服务的影响,可在确定好页面url或接口形式后,通过调用方通过mock测试数据来模拟交互,确定好测试用例,也方便了每次相关代码有修改进行回归测试。junit提供了对应的方法以方便测试。
import org.junit.Test; public class SimpleControllerTests { @Test public void simple() throws Exception { standaloneSetup(new SimpleController()).build() .perform(get("/simple")) // 模拟浏览器访问url .andExpect(status().isOk()) // andExpect 断言 判断请求返回的内容 .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) .andExpect(content().string("Hello world!")); // 内容是... } } public class StandardArgumentsControllerTests { private MockMvc mockMvc; @Before public void setup() throws Exception { // @org.junit.Before下需要实现setup类似于初始化的方法 this.mockMvc = standaloneSetup(new StandardArgumentsController()).alwaysExpect(status().isOk()).build(); // alwaysExpect } @Test public void request() throws Exception { this.mockMvc.perform(get("/data/standard/request")) // mock-get方法 .andExpect(content().string(startsWith( "request = org.springframework.mock.web.MockHttpServletRequest@"))); }
@Test
public void requestBody() throws Exception {
this.mockMvc.perform(
post("/data/body") // mock-post方法
.contentType(MediaType.TEXT_PLAIN)
.content("foo".getBytes()))
.andExpect(content().string("Posted request body 'foo'"));
}
5. 在本地启动jetty服务,运行java服务
详细步骤
a. 导入如上代码库工程到ide(如IDEA),系统自动选择maven构建和spring mvc依赖,导入后ide会花几分钟自动安装依赖,安装完后ide上可看到各级代码
b. 在项目根目录下执行mvn package 打包,执行完后,在target目录下产生spring-mvc-showcase.war
c. 在ide右上角绿色的运行按钮前,点击选择‘run/debug configurations’,进入设置子界面,点击左上角➕,找到jetty server,选择local 并进行简单的配置
d. 本地启动jetty服务 /opt/jetty/bin/jetty.sh start
Usage: jetty.sh [-d] {start|stop|run|restart|check|supervise} [ CONFIGS ... ]
/o/opt/jetty/bin/jetty.sh check // 另外check选项可以查询到jetty相关的配置路径 /usr/local/jetty-8/etc/jetty.xml中addConnector部分配置了jetty.port Checking arguments to Jetty: START_INI = /usr/local/jetty-8/start.ini JETTY_HOME = /usr/local/jetty-8 JETTY_BASE = /usr/local/jetty-8 JETTY_CONF = /usr/local/jetty-8/etc/jetty.conf JETTY_PID = /usr/local/jetty-8/jetty.pid JETTY_START = /usr/local/jetty-8/start.jar JETTY_LOGS = /usr/local/jetty-8/logs JETTY_STATE = /usr/local/jetty-8/jetty.state CLASSPATH = /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/lib/tools.jar JAVA = /usr/bin/java JAVA_OPTIONS = -Djetty.home=/usr/local/jetty-8 -Djetty.base=/usr/local/jetty-8 -Djava.io.tmpdir=/var/folders/hw/b3s7kxc173jfpf3kbty232m80000gn/T/ JETTY_ARGS = etc/jetty-started.xml RUN_CMD = /usr/bin/java -Djetty.home=/usr/local/jetty-8 -Djetty.base=/usr/local/jetty-8 -Djava.io.tmpdir=/var/folders/hw/b3s7kxc173jfpf3kbty232m80000gn/T/ -jar /usr/local/jetty-8/start.jar etc/jetty-started.xml
e. 在ide中点击右上角绿色运行按钮,运行war服务,注意观察terminal日志输出,判断是否成功启动服务
22:09:25 [Scanner-0] DispatcherServlet - Servlet 'appServlet' configured successfully
[2016-09-18 10:09:26,015] Artifact spring-mvc-showcase.war: Artifact is deployed successfully
[2016-09-18 10:09:26,017] Artifact spring-mvc-showcase.war: Deploy took 3,604 milliseconds
d. 打开浏览器访问
http://127.0.0.1:8081/
按上面提示再跳转到
http://127.0.0.1:8081/spring-mvc-showcase/ 进入项目首页
也可以直接访问单个请求入口,如 http://127.0.0.1:8081/spring-mvc-showcase//mapping/path