一. 创建简单工程
网页SpringBoot
进入[SpringBoot网站][],选择自己需要的依赖(Web,Velocity,AOP),生成工程,减少自己配置的工作量。
打开Idea,导入工程,然后静静等待一会即可。
[SpringBoot网站]:http://start.spring.io/
- 简单结构
web请求--->控制器---->服务---->DAO(--->数据库) - 注解和对应方法参数
//相对路径,参数value和path意义相同,可以写多个,{"/path1","/path2"}
@RequestMapping(value = {"/profile/{groupId}/{userId}"})
// 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
//根据返回的字符串,去资源文件夹下找匹配的文件,否则直接返回字符串,
@ResponseBody
//路径参数用PathVariable,请求参数用RequestParam
public String profile(@PathVariable("groupId") String groupId,
@PathVariable("userId") int userId,
@RequestParam(value = "type", defaultValue = "1") int type,
@RequestParam(value = "key", defaultValue = "nowcoder") String key) {
}
- Velocity 模板语法
##获取变量值
$!{变量/表达式}
#*多行
注释*#
##.index 0开始索引,.count为计数
#foreach($color in $colors)
Color$!(foreach.count)/$(foreach.index):$!(color)
#
- 资源文件
- 静态:static/templates css和images
- 模板文件: templates xxx.vn
a. 模板文件例子1
//java文件
@RequestMapping(value = {"/vm"})
//model 引入变量,多次使用时模板html中可以替换该值
public String news(Model model){
model.addAttribute("value1", "vv1");
List colors = Arrays.asList(new String[]{"RED", "GREEN", "BLUE"});
Map map = new HashMap();
for (int i = 0; i < 4; i++) {
map.put(String.valueOf(i), String.valueOf(i * i));
}
model.addAttribute("colors", colors);
model.addAttribute("map", map);
return "news";
}
//然后可以在模板文件夹下的news.vm文件中调用value1变量
Hello, VM
##你看不到我(注解格式)
$!{value1}##有则输出,无则空行
$!{value2}
${value3}##完整输出该字符
##for循环
#foreach ($color in $colors)
Color $!{foreach.index}/$!{foreach.count}:$!{color}
#end
#foreach($key in $map.keySet())
Number $!{foreach.index}/$!{foreach.count}:$!{key} $map.get($key)
#end
#foreach($kv in $map.entrySet())
Number $!{foreach.index}/$!{foreach.count}:$!{kv.key} $!{kv.value}
#end
User: $!{user.name}
User: $!{user.getName()}
#set($hello = "hello") ##类似宏定义
#set($hworld1 = "$!{hello} world")
#set($hworld2 = '$!{hello} world')
hworld1: $hworld1
hworld2: $hworld2
b. include和parse
##header.vm
Title $!title
##news.vm
##设置title变量值
#set($title = "nowcoder")
Include: #include("header.vm")
Parse: #parse("header.vm")
/*输出 Include: TiTle $!title Parse: TiTle nowcoder
说明,include嵌入文件,parse还会解析其中的变量*/
c. macro
#macro(render_color, $color, $index)
Color By Macro $index, $color
#end
#foreach ($color in $colors)
#render_color($color, $foreach.index)
#end
- 请求和响应
a. 请求
参数解析,cookie读取,http请求字段和文件上传
@RequestMapping(value = {"/request"})
@ResponseBody
//一般都设置这三个参数
public String request(HttpServletRequest req,
HttpServletResponse resp,
HttpSession session){
StringBuilder sb = new StringBuilder();
//获取请求头的名字,返回枚举类型
Enumeration headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
sb.append(name + ":" + req.getHeader(name) + "
");
}
return sb.toString();
}
b. 响应
页面内容返回,cookie下发,http字段设置,headers
@RequestMapping(value = {"/response"})
@ResponseBody
public String response(@CookieValue(value = "nowcoderid", defaultValue = "a") String nowcoderId,
@RequestParam(value = "key", defaultValue = "key") String key,
@RequestParam(value = "value", defaultValue = "value") String value,
HttpServletResponse resp) {
resp.addCookie(new Cookie(key,value));
resp.addHeader(key, value);
return "NowCoderId From COOkie: " + nowcoderId;}
- 重定向
301:永久转移,第一次访问后记录在浏览器中,再次访问时,直接跳重定向的路径,而不用先访问原地址。
302:临时转移,直接的方式return "redirect:/"
@RequestMapping("/redirect/{code}")
public RedirectView redirect(@PathVariable("code") int code) {
RedirectView red = new RedirectView("/",true);
if (code == 301) {
red.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
}
return red;
}
- 错误处理
@RequestMapping("/admin")
@ResponseBodypublic
String admin(@RequestParam(value = "key", required = false) String key){
if ("admin".equals(key)) {
return "Hello admin! ";
}
//没写异常处理,抛出异常,类似没找到资源,
throw new IllegalArgumentException("Key 错误");
}
/*结果:Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Nov 16 14:03:51 CST 2016
There was an unexpected error (type=Internal Server Error, status=500).
Key 错误*/
//写异常处理
@ExceptionHandler()
@ResponseBody
public String error(Exception e) {
return "error: " + e.getMessage();
}
//结果:error: Key 错误
- IoC:控制反转分成两种类型,依赖注入(DI)和依赖查找(DL),前者应用比较广泛,IoC一般指前者
//常规方式,通过构造器传参,类中的其他方法就可以调用
//Service.java
public String service(){
return "service()";
}
//Application.java
public String application(){
private Service service;
public Application(Service service){
this.service = service;
}
}
//注解方式,通过使用注解,spring自动匹配,可以直接调用,更方便
//Service.java
@Service
public String service(){
return "service()";
}
//Application.java
public String application(){
@AutoWired
private Service service;
}
}
- AOP:面向切面编程,所有业务都要处理的业务,比如log服务
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Before("execution(* com.nowcoder.controller.*Controller.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
StringBuilder sb = new StringBuilder();
for (Object arg : joinPoint.getArgs()) {
sb.append("arg:" + arg.toString() + "|");
}
logger.info("before time: " + new Date());
logger.info("before method: "+ sb.toString());
}
@After("execution(* com.nowcoder.controller.IndexController.*(..))")
public void afterMethod() {
logger.info("after method: ");
}
}