Skip to content

Java Web 开发指南

目录

Web 框架

Spring MVC

java
@Controller
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public String listUsers(Model model) {
        model.addAttribute("users", userService.findAll());
        return "users/list";
    }
    
    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id, Model model) {
        model.addAttribute("user", userService.findById(id));
        return "users/detail";
    }
    
    @GetMapping("/new")
    public String newUser(Model model) {
        model.addAttribute("user", new User());
        return "users/form";
    }
    
    @PostMapping
    public String createUser(@ModelAttribute User user) {
        userService.save(user);
        return "redirect:/users";
    }
}

Thymeleaf 模板

html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>用户列表</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>邮箱</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="user : ${users}">
                <td th:text="${user.id}"></td>
                <td th:text="${user.name}"></td>
                <td th:text="${user.email}"></td>
                <td>
                    <a th:href="@{/users/{id}(id=${user.id})}">查看</a>
                    <a th:href="@{/users/{id}/edit(id=${user.id})}">编辑</a>
                </td>
            </tr>
        </tbody>
    </table>
</body>
</html>

静态文件

静态资源处理

java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
    }
}

会话管理

Spring Session

java
@Configuration
@EnableRedisHttpSession
public class SessionConfig {
    
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory();
    }
}

@Controller
public class UserController {
    
    @PostMapping("/login")
    public String login(@RequestParam String username, 
                       @RequestParam String password,
                       HttpSession session) {
        User user = userService.authenticate(username, password);
        session.setAttribute("user", user);
        return "redirect:/";
    }
    
    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "redirect:/login";
    }
}

表单处理

表单验证

java
@Controller
public class UserController {
    
    @PostMapping("/register")
    public String register(@Valid @ModelAttribute User user, 
                          BindingResult result) {
        if (result.hasErrors()) {
            return "users/form";
        }
        userService.save(user);
        return "redirect:/users";
    }
}

public class User {
    @NotBlank(message = "姓名不能为空")
    private String name;
    
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @Size(min = 6, message = "密码长度不能小于6位")
    private String password;
}

文件上传

单文件上传

java
@Controller
public class FileController {
    
    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) {
        if (!file.isEmpty()) {
            try {
                String fileName = file.getOriginalFilename();
                String filePath = "uploads/" + fileName;
                File dest = new File(filePath);
                file.transferTo(dest);
                return "redirect:/success";
            } catch (IOException e) {
                return "redirect:/error";
            }
        }
        return "redirect:/error";
    }
}

多文件上传

java
@Controller
public class FileController {
    
    @PostMapping("/upload")
    public String uploadFiles(@RequestParam("files") MultipartFile[] files) {
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                try {
                    String fileName = file.getOriginalFilename();
                    String filePath = "uploads/" + fileName;
                    File dest = new File(filePath);
                    file.transferTo(dest);
                } catch (IOException e) {
                    return "redirect:/error";
                }
            }
        }
        return "redirect:/success";
    }
}

前端集成

集成 Vue.js

html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>用户管理</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
    <div id="app">
        <h1>用户列表</h1>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>姓名</th>
                    <th>邮箱</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="user in users">
                    <td>{{ user.id }}</td>
                    <td>{{ user.name }}</td>
                    <td>{{ user.email }}</td>
                    <td>
                        <button @click="editUser(user)">编辑</button>
                        <button @click="deleteUser(user.id)">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    
    <script>
        new Vue({
            el: '#app',
            data: {
                users: []
            },
            mounted() {
                this.loadUsers();
            },
            methods: {
                loadUsers() {
                    axios.get('/api/users')
                        .then(response => {
                            this.users = response.data;
                        });
                },
                editUser(user) {
                    // 处理编辑
                },
                deleteUser(id) {
                    axios.delete(`/api/users/${id}`)
                        .then(() => {
                            this.loadUsers();
                        });
                }
            }
        });
    </script>
</body>
</html>

性能优化

缓存控制

java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CacheControlInterceptor())
                .addPathPatterns("/static/**");
    }
}

public class CacheControlInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        response.setHeader("Cache-Control", "public, max-age=31536000");
        return true;
    }
}

压缩

java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorParameter(true)
                 .parameterName("mediaType")
                 .ignoreAcceptHeader(false)
                 .defaultContentType(MediaType.APPLICATION_JSON)
                 .mediaType("json", MediaType.APPLICATION_JSON)
                 .mediaType("xml", MediaType.APPLICATION_XML);
    }
}

安全实践

CSRF 保护

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated();
    }
}

XSS 防护

java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new XssInterceptor())
                .addPathPatterns("/**");
    }
}

public class XssInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        response.setHeader("X-XSS-Protection", "1; mode=block");
        response.setHeader("Content-Security-Policy", "default-src 'self'");
        return true;
    }
}

启航团队技术文档